1 // Copyright (c) 2012 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 BASE_MEMORY_SHARED_MEMORY_H_ 6 #define BASE_MEMORY_SHARED_MEMORY_H_ 7 8 #include "build/build_config.h" 9 10 #include <string> 11 12 #if defined(OS_POSIX) 13 #include <stdio.h> 14 #include <sys/types.h> 15 #include <semaphore.h> 16 #endif 17 18 #include "base/base_export.h" 19 #include "base/basictypes.h" 20 #include "base/process/process_handle.h" 21 22 #if defined(OS_POSIX) 23 #include "base/file_descriptor_posix.h" 24 #include "base/files/file_util.h" 25 #include "base/files/scoped_file.h" 26 #endif 27 28 namespace base { 29 30 class FilePath; 31 32 // SharedMemoryHandle is a platform specific type which represents 33 // the underlying OS handle to a shared memory segment. 34 #if defined(OS_WIN) 35 typedef HANDLE SharedMemoryHandle; 36 #elif defined(OS_POSIX) 37 // A SharedMemoryId is sufficient to identify a given shared memory segment on a 38 // system, but insufficient to map it. 39 typedef FileDescriptor SharedMemoryHandle; 40 typedef ino_t SharedMemoryId; 41 #endif 42 43 // Options for creating a shared memory object. 44 struct SharedMemoryCreateOptions { SharedMemoryCreateOptionsSharedMemoryCreateOptions45 SharedMemoryCreateOptions() 46 : name_deprecated(NULL), 47 size(0), 48 open_existing_deprecated(false), 49 executable(false), 50 share_read_only(false) {} 51 52 // DEPRECATED (crbug.com/345734): 53 // If NULL, the object is anonymous. This pointer is owned by the caller 54 // and must live through the call to Create(). 55 const std::string* name_deprecated; 56 57 // Size of the shared memory object to be created. 58 // When opening an existing object, this has no effect. 59 size_t size; 60 61 // DEPRECATED (crbug.com/345734): 62 // If true, and the shared memory already exists, Create() will open the 63 // existing shared memory and ignore the size parameter. If false, 64 // shared memory must not exist. This flag is meaningless unless 65 // name_deprecated is non-NULL. 66 bool open_existing_deprecated; 67 68 // If true, mappings might need to be made executable later. 69 bool executable; 70 71 // If true, the file can be shared read-only to a process. 72 bool share_read_only; 73 }; 74 75 // Platform abstraction for shared memory. Provides a C++ wrapper 76 // around the OS primitive for a memory mapped file. 77 class BASE_EXPORT SharedMemory { 78 public: 79 SharedMemory(); 80 81 #if defined(OS_WIN) 82 // Similar to the default constructor, except that this allows for 83 // calling LockDeprecated() to acquire the named mutex before either Create or 84 // Open are called on Windows. 85 explicit SharedMemory(const std::wstring& name); 86 #endif 87 88 // Create a new SharedMemory object from an existing, open 89 // shared memory file. 90 // 91 // WARNING: This does not reduce the OS-level permissions on the handle; it 92 // only affects how the SharedMemory will be mmapped. Use 93 // ShareReadOnlyToProcess to drop permissions. TODO(jln,jyasskin): DCHECK 94 // that |read_only| matches the permissions of the handle. 95 SharedMemory(SharedMemoryHandle handle, bool read_only); 96 97 // Create a new SharedMemory object from an existing, open 98 // shared memory file that was created by a remote process and not shared 99 // to the current process. 100 SharedMemory(SharedMemoryHandle handle, bool read_only, 101 ProcessHandle process); 102 103 // Closes any open files. 104 ~SharedMemory(); 105 106 // Return true iff the given handle is valid (i.e. not the distingished 107 // invalid value; NULL for a HANDLE and -1 for a file descriptor) 108 static bool IsHandleValid(const SharedMemoryHandle& handle); 109 110 // Returns invalid handle (see comment above for exact definition). 111 static SharedMemoryHandle NULLHandle(); 112 113 // Closes a shared memory handle. 114 static void CloseHandle(const SharedMemoryHandle& handle); 115 116 // Returns the maximum number of handles that can be open at once per process. 117 static size_t GetHandleLimit(); 118 119 // Creates a shared memory object as described by the options struct. 120 // Returns true on success and false on failure. 121 bool Create(const SharedMemoryCreateOptions& options); 122 123 // Creates and maps an anonymous shared memory segment of size size. 124 // Returns true on success and false on failure. 125 bool CreateAndMapAnonymous(size_t size); 126 127 // Creates an anonymous shared memory segment of size size. 128 // Returns true on success and false on failure. CreateAnonymous(size_t size)129 bool CreateAnonymous(size_t size) { 130 SharedMemoryCreateOptions options; 131 options.size = size; 132 return Create(options); 133 } 134 135 // DEPRECATED (crbug.com/345734): 136 // Creates or opens a shared memory segment based on a name. 137 // If open_existing is true, and the shared memory already exists, 138 // opens the existing shared memory and ignores the size parameter. 139 // If open_existing is false, shared memory must not exist. 140 // size is the size of the block to be created. 141 // Returns true on success, false on failure. CreateNamedDeprecated(const std::string & name,bool open_existing,size_t size)142 bool CreateNamedDeprecated( 143 const std::string& name, bool open_existing, size_t size) { 144 SharedMemoryCreateOptions options; 145 options.name_deprecated = &name; 146 options.open_existing_deprecated = open_existing; 147 options.size = size; 148 return Create(options); 149 } 150 151 // Deletes resources associated with a shared memory segment based on name. 152 // Not all platforms require this call. 153 bool Delete(const std::string& name); 154 155 // Opens a shared memory segment based on a name. 156 // If read_only is true, opens for read-only access. 157 // Returns true on success, false on failure. 158 bool Open(const std::string& name, bool read_only); 159 160 // Maps the shared memory into the caller's address space. 161 // Returns true on success, false otherwise. The memory address 162 // is accessed via the memory() accessor. The mapped address is guaranteed to 163 // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail 164 // if this object is currently mapped. Map(size_t bytes)165 bool Map(size_t bytes) { 166 return MapAt(0, bytes); 167 } 168 169 // Same as above, but with |offset| to specify from begining of the shared 170 // memory block to map. 171 // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|. 172 bool MapAt(off_t offset, size_t bytes); 173 enum { MAP_MINIMUM_ALIGNMENT = 32 }; 174 175 // Unmaps the shared memory from the caller's address space. 176 // Returns true if successful; returns false on error or if the 177 // memory is not mapped. 178 bool Unmap(); 179 180 // The size requested when the map is first created. requested_size()181 size_t requested_size() const { return requested_size_; } 182 183 // The actual size of the mapped memory (may be larger than requested). mapped_size()184 size_t mapped_size() const { return mapped_size_; } 185 186 // Gets a pointer to the opened memory space if it has been 187 // Mapped via Map(). Returns NULL if it is not mapped. memory()188 void *memory() const { return memory_; } 189 190 // Returns the underlying OS handle for this segment. 191 // Use of this handle for anything other than an opaque 192 // identifier is not portable. 193 SharedMemoryHandle handle() const; 194 195 #if defined(OS_POSIX) && !defined(OS_NACL) 196 // Returns a unique identifier for this shared memory segment. Inode numbers 197 // are technically only unique to a single filesystem. However, we always 198 // allocate shared memory backing files from the same directory, so will end 199 // up on the same filesystem. id()200 SharedMemoryId id() const { return inode_; } 201 #endif 202 203 // Closes the open shared memory segment. 204 // It is safe to call Close repeatedly. 205 void Close(); 206 207 // Shares the shared memory to another process. Attempts to create a 208 // platform-specific new_handle which can be used in a remote process to read 209 // the shared memory file. new_handle is an output parameter to receive the 210 // handle for use in the remote process. 211 // 212 // |*this| must have been initialized using one of the Create*() or Open() 213 // methods with share_read_only=true. If it was constructed from a 214 // SharedMemoryHandle, this call will CHECK-fail. 215 // 216 // Returns true on success, false otherwise. ShareReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)217 bool ShareReadOnlyToProcess(ProcessHandle process, 218 SharedMemoryHandle* new_handle) { 219 return ShareToProcessCommon(process, new_handle, false, SHARE_READONLY); 220 } 221 222 // Logically equivalent to: 223 // bool ok = ShareReadOnlyToProcess(process, new_handle); 224 // Close(); 225 // return ok; 226 // Note that the memory is unmapped by calling this method, regardless of the 227 // return value. GiveReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)228 bool GiveReadOnlyToProcess(ProcessHandle process, 229 SharedMemoryHandle* new_handle) { 230 return ShareToProcessCommon(process, new_handle, true, SHARE_READONLY); 231 } 232 233 // Shares the shared memory to another process. Attempts 234 // to create a platform-specific new_handle which can be 235 // used in a remote process to access the shared memory 236 // file. new_handle is an output parameter to receive 237 // the handle for use in the remote process. 238 // Returns true on success, false otherwise. ShareToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)239 bool ShareToProcess(ProcessHandle process, 240 SharedMemoryHandle* new_handle) { 241 return ShareToProcessCommon(process, new_handle, false, SHARE_CURRENT_MODE); 242 } 243 244 // Logically equivalent to: 245 // bool ok = ShareToProcess(process, new_handle); 246 // Close(); 247 // return ok; 248 // Note that the memory is unmapped by calling this method, regardless of the 249 // return value. GiveToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)250 bool GiveToProcess(ProcessHandle process, 251 SharedMemoryHandle* new_handle) { 252 return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE); 253 } 254 255 // DEPRECATED (crbug.com/345734): 256 // Locks the shared memory. 257 // 258 // WARNING: on POSIX the memory locking primitive only works across 259 // processes, not across threads. The LockDeprecated method is not currently 260 // used in inner loops, so we protect against multiple threads in a 261 // critical section using a class global lock. 262 void LockDeprecated(); 263 264 // DEPRECATED (crbug.com/345734): 265 // Releases the shared memory lock. 266 void UnlockDeprecated(); 267 268 private: 269 #if defined(OS_POSIX) && !defined(OS_NACL) 270 #if !defined(OS_ANDROID) 271 bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly); 272 bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); 273 #endif 274 void LockOrUnlockCommon(int function); 275 #endif // defined(OS_POSIX) && !defined(OS_NACL) 276 enum ShareMode { 277 SHARE_READONLY, 278 SHARE_CURRENT_MODE, 279 }; 280 bool ShareToProcessCommon(ProcessHandle process, 281 SharedMemoryHandle* new_handle, 282 bool close_self, 283 ShareMode); 284 285 #if defined(OS_WIN) 286 std::wstring name_; 287 HANDLE mapped_file_; 288 #elif defined(OS_POSIX) 289 int mapped_file_; 290 int readonly_mapped_file_; 291 ino_t inode_; 292 #endif 293 size_t mapped_size_; 294 void* memory_; 295 bool read_only_; 296 size_t requested_size_; 297 #if !defined(OS_POSIX) 298 HANDLE lock_; 299 #endif 300 301 DISALLOW_COPY_AND_ASSIGN(SharedMemory); 302 }; 303 304 // DEPRECATED (crbug.com/345734): 305 // A helper class that acquires the shared memory lock while 306 // the SharedMemoryAutoLockDeprecated is in scope. 307 class SharedMemoryAutoLockDeprecated { 308 public: SharedMemoryAutoLockDeprecated(SharedMemory * shared_memory)309 explicit SharedMemoryAutoLockDeprecated(SharedMemory* shared_memory) 310 : shared_memory_(shared_memory) { 311 shared_memory_->LockDeprecated(); 312 } 313 ~SharedMemoryAutoLockDeprecated()314 ~SharedMemoryAutoLockDeprecated() { 315 shared_memory_->UnlockDeprecated(); 316 } 317 318 private: 319 SharedMemory* shared_memory_; 320 DISALLOW_COPY_AND_ASSIGN(SharedMemoryAutoLockDeprecated); 321 }; 322 323 } // namespace base 324 325 #endif // BASE_MEMORY_SHARED_MEMORY_H_ 326