Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_ipc_SharedMemory_h
8 : #define mozilla_ipc_SharedMemory_h
9 :
10 : #include "nsDebug.h"
11 : #include "nsISupportsImpl.h" // NS_INLINE_DECL_REFCOUNTING
12 : #include "mozilla/Attributes.h"
13 :
14 : #include "base/process.h"
15 : #include "chrome/common/ipc_message_utils.h"
16 :
17 : //
18 : // This is a low-level wrapper around platform shared memory. Don't
19 : // use it directly; use Shmem allocated through IPDL interfaces.
20 : //
21 : namespace {
22 : enum Rights {
23 : RightsNone = 0,
24 : RightsRead = 1 << 0,
25 : RightsWrite = 1 << 1
26 : };
27 : } // namespace
28 :
29 : namespace mozilla {
30 :
31 : namespace ipc {
32 : class SharedMemory;
33 : } // namespace ipc
34 :
35 : namespace ipc {
36 :
37 : class SharedMemory
38 : {
39 : protected:
40 37 : virtual ~SharedMemory()
41 74 : {
42 37 : Unmapped();
43 37 : Destroyed();
44 37 : }
45 :
46 : public:
47 : enum SharedMemoryType {
48 : TYPE_BASIC,
49 : TYPE_UNKNOWN
50 : };
51 :
52 : enum OpenRights {
53 : RightsReadOnly = RightsRead,
54 : RightsReadWrite = RightsRead | RightsWrite,
55 : };
56 :
57 54 : size_t Size() const { return mMappedSize; }
58 :
59 : virtual void* memory() const = 0;
60 :
61 : virtual bool Create(size_t size) = 0;
62 : virtual bool Map(size_t nBytes) = 0;
63 :
64 : virtual void CloseHandle() = 0;
65 :
66 : virtual SharedMemoryType Type() const = 0;
67 :
68 : virtual bool ShareHandle(base::ProcessId aProcessId, IPC::Message* aMessage) = 0;
69 : virtual bool ReadHandle(const IPC::Message* aMessage, PickleIterator* aIter) = 0;
70 :
71 : void
72 30 : Protect(char* aAddr, size_t aSize, int aRights)
73 : {
74 30 : char* memStart = reinterpret_cast<char*>(memory());
75 30 : if (!memStart)
76 0 : MOZ_CRASH("SharedMemory region points at NULL!");
77 30 : char* memEnd = memStart + Size();
78 :
79 30 : char* protStart = aAddr;
80 30 : if (!protStart)
81 0 : MOZ_CRASH("trying to Protect() a NULL region!");
82 30 : char* protEnd = protStart + aSize;
83 :
84 30 : if (!(memStart <= protStart
85 : && protEnd <= memEnd))
86 0 : MOZ_CRASH("attempt to Protect() a region outside this SharedMemory");
87 :
88 : // checks alignment etc.
89 30 : SystemProtect(aAddr, aSize, aRights);
90 30 : }
91 :
92 : // 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
93 210 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedMemory)
94 :
95 : static void SystemProtect(char* aAddr, size_t aSize, int aRights);
96 : static size_t SystemPageSize();
97 : static size_t PageAlignedSize(size_t aSize);
98 :
99 : protected:
100 : SharedMemory();
101 :
102 : // Implementations should call these methods on shmem usage changes,
103 : // but *only if* the OS-specific calls are known to have succeeded.
104 : // The methods are expected to be called in the pattern
105 : //
106 : // Created (Mapped Unmapped)* Destroy
107 : //
108 : // but this isn't checked.
109 : void Created(size_t aNBytes);
110 : void Mapped(size_t aNBytes);
111 : void Unmapped();
112 : void Destroyed();
113 :
114 : // The size of the shmem region requested in Create(), if
115 : // successful. SharedMemory instances that are opened from a
116 : // foreign handle have an alloc size of 0, even though they have
117 : // access to the alloc-size information.
118 : size_t mAllocSize;
119 : // The size of the region mapped in Map(), if successful. All
120 : // SharedMemorys that are mapped have a non-zero mapped size.
121 : size_t mMappedSize;
122 : };
123 :
124 : template<typename HandleImpl>
125 87 : class SharedMemoryCommon : public SharedMemory
126 : {
127 : public:
128 : typedef HandleImpl Handle;
129 :
130 : virtual bool ShareToProcess(base::ProcessId aProcessId, Handle* aHandle) = 0;
131 : virtual bool IsHandleValid(const Handle& aHandle) const = 0;
132 : virtual bool SetHandle(const Handle& aHandle, OpenRights aRights) = 0;
133 :
134 3 : virtual bool ShareHandle(base::ProcessId aProcessId, IPC::Message* aMessage) override
135 : {
136 3 : Handle handle;
137 3 : if (!ShareToProcess(aProcessId, &handle)) {
138 0 : return false;
139 : }
140 3 : IPC::WriteParam(aMessage, handle);
141 3 : return true;
142 : }
143 :
144 2 : virtual bool ReadHandle(const IPC::Message* aMessage, PickleIterator* aIter) override
145 : {
146 2 : Handle handle;
147 4 : return IPC::ReadParam(aMessage, aIter, &handle) &&
148 4 : IsHandleValid(handle) &&
149 4 : SetHandle(handle, RightsReadWrite);
150 : }
151 : };
152 :
153 : } // namespace ipc
154 : } // namespace mozilla
155 :
156 :
157 : #endif // ifndef mozilla_ipc_SharedMemory_h
|