LCOV - code coverage report
Current view: directory - objdir/dist/include/mozilla/ipc - Shmem.h (source / functions) Found Hit Coverage
Test: app.info Lines: 51 0 0.0 %
Date: 2012-06-02 Functions: 19 0 0.0 %

       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                 : #ifndef mozilla_ipc_Shmem_h
      42                 : #define mozilla_ipc_Shmem_h
      43                 : 
      44                 : #include "mozilla/Attributes.h"
      45                 : 
      46                 : #include "base/basictypes.h"
      47                 : #include "base/process.h"
      48                 : 
      49                 : #include "nscore.h"
      50                 : #include "nsDebug.h"
      51                 : 
      52                 : #include "IPC/IPCMessageUtils.h"
      53                 : #include "mozilla/ipc/SharedMemory.h"
      54                 : 
      55                 : /**
      56                 :  * |Shmem| is one agent in the IPDL shared memory scheme.  The way it
      57                 :     works is essentially
      58                 :  *
      59                 :  *  (1) C++ code calls, say, |parentActor->AllocShmem(size)|
      60                 : 
      61                 :  *  (2) IPDL-generated code creates a |mozilla::ipc::SharedMemory|
      62                 :  *  wrapping the bare OS shmem primitives.  The code then adds the new
      63                 :  *  SharedMemory to the set of shmem segments being managed by IPDL.
      64                 :  *
      65                 :  *  (3) IPDL-generated code "shares" the new SharedMemory to the child
      66                 :  *  process, and then sends a special asynchronous IPC message to the
      67                 :  *  child notifying it of the creation of the segment.  (What this
      68                 :  *  means is OS specific.)
      69                 :  *
      70                 :  *  (4a) The child receives the special IPC message, and using the
      71                 :  *  |SharedMemory{SysV,Basic}::Handle| it was passed, creates a
      72                 :  *  |mozilla::ipc::SharedMemory| in the child
      73                 :  *  process.
      74                 :  *
      75                 :  *  (4b) After sending the "shmem-created" IPC message, IPDL-generated
      76                 :  *  code in the parent returns a |mozilla::ipc::Shmem| back to the C++
      77                 :  *  caller of |parentActor->AllocShmem()|.  The |Shmem| is a "weak
      78                 :  *  reference" to the underlying |SharedMemory|, which is managed by
      79                 :  *  IPDL-generated code.  C++ consumers of |Shmem| can't get at the
      80                 :  *  underlying |SharedMemory|.
      81                 :  *
      82                 :  * If parent code wants to give access rights to the Shmem to the
      83                 :  * child, it does so by sending its |Shmem| to the child, in an IPDL
      84                 :  * message.  The parent's |Shmem| then "dies", i.e. becomes
      85                 :  * inaccessible.  This process could be compared to passing a
      86                 :  * "shmem-access baton" between parent and child.
      87                 :  */
      88                 : 
      89                 : namespace mozilla {
      90                 : namespace ipc {
      91                 : 
      92                 : class Shmem MOZ_FINAL
      93                 : {
      94                 :   friend struct IPC::ParamTraits<mozilla::ipc::Shmem>;
      95                 : 
      96                 : public:
      97                 :   typedef int32 id_t;
      98                 :   // Low-level wrapper around platform shmem primitives.
      99                 :   typedef mozilla::ipc::SharedMemory SharedMemory;
     100                 :   typedef SharedMemory::SharedMemoryType SharedMemoryType;
     101                 :   struct IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead {};
     102                 : 
     103               0 :   Shmem() :
     104                 :     mSegment(0),
     105                 :     mData(0),
     106                 :     mSize(0),
     107               0 :     mId(0)
     108                 :   {
     109               0 :   }
     110                 : 
     111               0 :   Shmem(const Shmem& aOther) :
     112                 :     mSegment(aOther.mSegment),
     113                 :     mData(aOther.mData),
     114                 :     mSize(aOther.mSize),
     115               0 :     mId(aOther.mId)
     116                 :   {
     117               0 :   }
     118                 : 
     119                 : #if !defined(DEBUG)
     120                 :   Shmem(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     121                 :         SharedMemory* aSegment, id_t aId) :
     122                 :     mSegment(aSegment),
     123                 :     mData(aSegment->memory()),
     124                 :     mSize(0),
     125                 :     mId(aId)
     126                 :   {
     127                 :     mSize = static_cast<size_t>(*PtrToSize(mSegment));
     128                 :   }
     129                 : #else
     130                 :   Shmem(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     131                 :         SharedMemory* aSegment, id_t aId);
     132                 : #endif
     133                 : 
     134               0 :   ~Shmem()
     135                 :   {
     136                 :     // Shmem only holds a "weak ref" to the actual segment, which is
     137                 :     // owned by IPDL. So there's nothing interesting to be done here
     138               0 :     forget(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead());
     139               0 :   }
     140                 : 
     141               0 :   Shmem& operator=(const Shmem& aRhs)
     142                 :   {
     143               0 :     mSegment = aRhs.mSegment;
     144               0 :     mData = aRhs.mData;
     145               0 :     mSize = aRhs.mSize;
     146               0 :     mId = aRhs.mId;
     147               0 :     return *this;
     148                 :   }
     149                 : 
     150               0 :   bool operator==(const Shmem& aRhs) const
     151                 :   {
     152                 :     // need to compare IDs because of AdoptShmem(); two Shmems might
     153                 :     // refer to the same segment but with different IDs for different
     154                 :     // protocol trees.  (NB: it's possible for this method to
     155                 :     // spuriously return true if AdoptShmem() gives the same ID for
     156                 :     // two protocol trees, but I don't think that can cause any
     157                 :     // problems since the Shmems really would be indistinguishable.)
     158               0 :     return mSegment == aRhs.mSegment && mId == aRhs.mId;
     159                 :   }
     160                 : 
     161                 :   // Returns whether this Shmem is writable by you, and thus whether you can
     162                 :   // transfer writability to another actor.
     163                 :   bool
     164               0 :   IsWritable() const
     165                 :   {
     166               0 :     return mSegment != NULL;
     167                 :   }
     168                 : 
     169                 :   // Returns whether this Shmem is readable by you, and thus whether you can
     170                 :   // transfer readability to another actor.
     171                 :   bool
     172               0 :   IsReadable() const
     173                 :   {
     174               0 :     return mSegment != NULL;
     175                 :   }
     176                 : 
     177                 :   // Return a pointer to the user-visible data segment.
     178                 :   template<typename T>
     179                 :   T*
     180               0 :   get() const
     181                 :   {
     182               0 :     AssertInvariants();
     183               0 :     AssertAligned<T>();
     184                 : 
     185               0 :     return reinterpret_cast<T*>(mData);
     186                 :   }
     187                 : 
     188                 :   // Return the size of the segment as requested when this shmem
     189                 :   // segment was allocated, in units of T.  The underlying mapping may
     190                 :   // actually be larger because of page alignment and private data,
     191                 :   // but this isn't exposed to clients.
     192                 :   template<typename T>
     193                 :   size_t
     194               0 :   Size() const
     195                 :   {
     196               0 :     AssertInvariants();
     197               0 :     AssertAligned<T>();
     198                 : 
     199               0 :     return mSize / sizeof(T);
     200                 :   }
     201                 : 
     202                 :   int GetSysVID() const;
     203                 : 
     204                 :   // These shouldn't be used directly, use the IPDL interface instead.
     205               0 :   id_t Id(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) const {
     206               0 :     return mId;
     207                 :   }
     208                 : 
     209               0 :   SharedMemory* Segment(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead) const {
     210               0 :     return mSegment;
     211                 :   }
     212                 : 
     213                 : #ifndef DEBUG
     214                 :   void RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead)
     215                 :   {
     216                 :   }
     217                 : #else
     218                 :   void RevokeRights(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead);
     219                 : #endif
     220                 : 
     221               0 :   void forget(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead)
     222                 :   {
     223               0 :     mSegment = 0;
     224               0 :     mData = 0;
     225               0 :     mSize = 0;
     226               0 :     mId = 0;
     227               0 :   }
     228                 : 
     229                 :   static SharedMemory*
     230                 :   Alloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     231                 :         size_t aNBytes,
     232                 :         SharedMemoryType aType,
     233                 :         bool aUnsafe,
     234                 :         bool aProtect=false);
     235                 : 
     236                 :   // Prepare this to be shared with |aProcess|.  Return an IPC message
     237                 :   // that contains enough information for the other process to map
     238                 :   // this segment in OpenExisting() below.  Return a new message if
     239                 :   // successful (owned by the caller), NULL if not.
     240                 :   IPC::Message*
     241                 :   ShareTo(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     242                 :           base::ProcessHandle aProcess,
     243                 :           int32 routingId);
     244                 : 
     245                 :   // Stop sharing this with |aProcess|.  Return an IPC message that
     246                 :   // contains enough information for the other process to unmap this
     247                 :   // segment.  Return a new message if successful (owned by the
     248                 :   // caller), NULL if not.
     249                 :   IPC::Message*
     250                 :   UnshareFrom(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     251                 :               base::ProcessHandle aProcess,
     252                 :               int32 routingId);
     253                 : 
     254                 :   // Return a SharedMemory instance in this process using the
     255                 :   // descriptor shared to us by the process that created the
     256                 :   // underlying OS shmem resource.  The contents of the descriptor
     257                 :   // depend on the type of SharedMemory that was passed to us.
     258                 :   static SharedMemory*
     259                 :   OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     260                 :                const IPC::Message& aDescriptor,
     261                 :                id_t* aId,
     262                 :                bool aProtect=false);
     263                 : 
     264                 :   static void
     265                 :   Dealloc(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead,
     266                 :           SharedMemory* aSegment);
     267                 : 
     268                 : private:
     269                 :   template<typename T>
     270               0 :   void AssertAligned() const
     271                 :   {
     272               0 :     if (0 != (mSize % sizeof(T)))
     273               0 :       NS_RUNTIMEABORT("shmem is not T-aligned");
     274               0 :   }
     275                 : 
     276                 : #if !defined(DEBUG)
     277                 :   void AssertInvariants() const
     278                 :   { }
     279                 : 
     280                 :   static uint32*
     281                 :   PtrToSize(SharedMemory* aSegment)
     282                 :   {
     283                 :     char* endOfSegment =
     284                 :       reinterpret_cast<char*>(aSegment->memory()) + aSegment->Size();
     285                 :     return reinterpret_cast<uint32*>(endOfSegment - sizeof(uint32));
     286                 :   }
     287                 : 
     288                 : #else
     289                 :   void AssertInvariants() const;
     290                 : #endif
     291                 : 
     292                 :   SharedMemory* mSegment;
     293                 :   void* mData;
     294                 :   size_t mSize;
     295                 :   id_t mId;
     296                 : };
     297                 : 
     298                 : 
     299                 : } // namespace ipc
     300                 : } // namespace mozilla
     301                 : 
     302                 : 
     303                 : namespace IPC {
     304                 : 
     305                 : template<>
     306                 : struct ParamTraits<mozilla::ipc::Shmem>
     307                 : {
     308                 :   typedef mozilla::ipc::Shmem paramType;
     309                 : 
     310                 :   // NB: Read()/Write() look creepy in that Shmems have a pointer
     311                 :   // member, but IPDL internally uses mId to properly initialize a
     312                 :   // "real" Shmem
     313                 : 
     314               0 :   static void Write(Message* aMsg, const paramType& aParam)
     315                 :   {
     316               0 :     WriteParam(aMsg, aParam.mId);
     317               0 :   }
     318                 : 
     319               0 :   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
     320                 :   {
     321                 :     paramType::id_t id;
     322               0 :     if (!ReadParam(aMsg, aIter, &id))
     323               0 :       return false;
     324               0 :     aResult->mId = id;
     325               0 :     return true;
     326                 :   }
     327                 : 
     328                 :   static void Log(const paramType& aParam, std::wstring* aLog)
     329                 :   {
     330                 :     aLog->append(L"(shmem segment)");
     331                 :   }
     332                 : };
     333                 : 
     334                 : 
     335                 : } // namespace IPC
     336                 : 
     337                 : 
     338                 : #endif // ifndef mozilla_ipc_Shmem_h

Generated by: LCOV version 1.7