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