• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
6 #define MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
7 
8 #include <stddef.h>
9 
10 #include <memory>
11 
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/shared_memory.h"
15 #include "base/memory/shared_memory_handle.h"
16 #include "base/synchronization/lock.h"
17 #include "mojo/edk/embedder/scoped_platform_handle.h"
18 #include "mojo/edk/system/system_impl_export.h"
19 
20 namespace mojo {
21 namespace edk {
22 
23 class PlatformSharedBufferMapping;
24 
25 // |PlatformSharedBuffer| is a thread-safe, ref-counted wrapper around
26 // OS-specific shared memory. It has the following features:
27 //   - A |PlatformSharedBuffer| simply represents a piece of shared memory that
28 //     *may* be mapped and *may* be shared to another process.
29 //   - A single |PlatformSharedBuffer| may be mapped multiple times. The
30 //     lifetime of the mapping (owned by |PlatformSharedBufferMapping|) is
31 //     separate from the lifetime of the |PlatformSharedBuffer|.
32 //   - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not
33 //     restricted by page size. However, more memory may actually be mapped than
34 //     requested.
35 class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBuffer
36     : public base::RefCountedThreadSafe<PlatformSharedBuffer> {
37  public:
38   // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled).
39   // |num_bytes| must be nonzero. Returns null on failure.
40   static PlatformSharedBuffer* Create(size_t num_bytes);
41 
42   // Creates a shared buffer of size |num_bytes| from the existing platform
43   // handle |platform_handle|. Returns null on failure.
44   static PlatformSharedBuffer* CreateFromPlatformHandle(
45       size_t num_bytes,
46       bool read_only,
47       ScopedPlatformHandle platform_handle);
48 
49   // Creates a shared buffer of size |num_bytes| from the existing pair of
50   // read/write and read-only handles |rw_platform_handle| and
51   // |ro_platform_handle|. Returns null on failure.
52   static PlatformSharedBuffer* CreateFromPlatformHandlePair(
53       size_t num_bytes,
54       ScopedPlatformHandle rw_platform_handle,
55       ScopedPlatformHandle ro_platform_handle);
56 
57   // Creates a shared buffer of size |num_bytes| from the existing shared memory
58   // handle |handle|.
59   static PlatformSharedBuffer* CreateFromSharedMemoryHandle(
60       size_t num_bytes,
61       bool read_only,
62       base::SharedMemoryHandle handle);
63 
64   // Gets the size of shared buffer (in number of bytes).
65   size_t GetNumBytes() const;
66 
67   // Returns whether this shared buffer is read-only.
68   bool IsReadOnly() const;
69 
70   // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|]
71   // must be contained in [0, |num_bytes|], and |length| must be at least 1.
72   // Returns null on failure.
73   std::unique_ptr<PlatformSharedBufferMapping> Map(size_t offset,
74                                                    size_t length);
75 
76   // Checks if |offset| and |length| are valid arguments.
77   bool IsValidMap(size_t offset, size_t length);
78 
79   // Like |Map()|, but doesn't check its arguments (which should have been
80   // preflighted using |IsValidMap()|).
81   std::unique_ptr<PlatformSharedBufferMapping> MapNoCheck(size_t offset,
82                                                           size_t length);
83 
84   // Duplicates the underlying platform handle and passes it to the caller.
85   ScopedPlatformHandle DuplicatePlatformHandle();
86 
87   // Duplicates the underlying shared memory handle and passes it to the caller.
88   base::SharedMemoryHandle DuplicateSharedMemoryHandle();
89 
90   // Passes the underlying platform handle to the caller. This should only be
91   // called if there's a unique reference to this object (owned by the caller).
92   // After calling this, this object should no longer be used, but should only
93   // be disposed of.
94   ScopedPlatformHandle PassPlatformHandle();
95 
96   // Create and return a read-only duplicate of this shared buffer. If this
97   // shared buffer isn't capable of returning a read-only duplicate, then
98   // nullptr will be returned.
99   PlatformSharedBuffer* CreateReadOnlyDuplicate();
100 
101  private:
102   friend class base::RefCountedThreadSafe<PlatformSharedBuffer>;
103 
104   PlatformSharedBuffer(size_t num_bytes, bool read_only);
105   ~PlatformSharedBuffer();
106 
107   // This is called by |Create()| before this object is given to anyone.
108   bool Init();
109 
110   // This is like |Init()|, but for |CreateFromPlatformHandle()|. (Note: It
111   // should verify that |platform_handle| is an appropriate handle for the
112   // claimed |num_bytes_|.)
113   bool InitFromPlatformHandle(ScopedPlatformHandle platform_handle);
114 
115   bool InitFromPlatformHandlePair(ScopedPlatformHandle rw_platform_handle,
116                                   ScopedPlatformHandle ro_platform_handle);
117 
118   void InitFromSharedMemoryHandle(base::SharedMemoryHandle handle);
119 
120   const size_t num_bytes_;
121   const bool read_only_;
122 
123   base::Lock lock_;
124   std::unique_ptr<base::SharedMemory> shared_memory_;
125 
126   // A separate read-only shared memory for platforms that need it (i.e. Linux
127   // with sync broker).
128   std::unique_ptr<base::SharedMemory> ro_shared_memory_;
129 
130   DISALLOW_COPY_AND_ASSIGN(PlatformSharedBuffer);
131 };
132 
133 // A mapping of a |PlatformSharedBuffer| (compararable to a "file view" in
134 // Windows); see above. Created by |PlatformSharedBuffer::Map()|. Automatically
135 // unmaps memory on destruction.
136 //
137 // Mappings are NOT thread-safe.
138 //
139 // Note: This is an entirely separate class (instead of
140 // |PlatformSharedBuffer::Mapping|) so that it can be forward-declared.
141 class MOJO_SYSTEM_IMPL_EXPORT PlatformSharedBufferMapping {
142  public:
143   ~PlatformSharedBufferMapping();
144 
145   void* GetBase() const;
146   size_t GetLength() const;
147 
148  private:
149   friend class PlatformSharedBuffer;
150 
PlatformSharedBufferMapping(base::SharedMemoryHandle handle,bool read_only,size_t offset,size_t length)151   PlatformSharedBufferMapping(base::SharedMemoryHandle handle,
152                               bool read_only,
153                               size_t offset,
154                               size_t length)
155       : offset_(offset),
156         length_(length),
157         base_(nullptr),
158         shared_memory_(handle, read_only) {}
159 
160   bool Map();
161   void Unmap();
162 
163   const size_t offset_;
164   const size_t length_;
165   void* base_;
166 
167   // Since mapping life cycles are separate from PlatformSharedBuffer and a
168   // buffer can be mapped multiple times, we have our own SharedMemory object
169   // created from a duplicate handle.
170   base::SharedMemory shared_memory_;
171 
172   DISALLOW_COPY_AND_ASSIGN(PlatformSharedBufferMapping);
173 };
174 
175 }  // namespace edk
176 }  // namespace mojo
177 
178 #endif  // MOJO_EDK_EMBEDDER_PLATFORM_SHARED_BUFFER_H_
179