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