1 // Copyright (c) 2011 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_SHARED_MEMORY_H_ 6 #define BASE_SHARED_MEMORY_H_ 7 #pragma once 8 9 #include "build/build_config.h" 10 11 #if defined(OS_POSIX) 12 #include <sys/types.h> 13 #include <semaphore.h> 14 #include "base/file_descriptor_posix.h" 15 #endif 16 #include <string> 17 18 #include "base/base_api.h" 19 #include "base/basictypes.h" 20 #include "base/process.h" 21 22 class FilePath; 23 24 namespace base { 25 26 // SharedMemoryHandle is a platform specific type which represents 27 // the underlying OS handle to a shared memory segment. 28 #if defined(OS_WIN) 29 typedef HANDLE SharedMemoryHandle; 30 typedef HANDLE SharedMemoryLock; 31 #elif defined(OS_POSIX) 32 // A SharedMemoryId is sufficient to identify a given shared memory segment on a 33 // system, but insufficient to map it. 34 typedef FileDescriptor SharedMemoryHandle; 35 typedef ino_t SharedMemoryId; 36 // On POSIX, the lock is implemented as a lockf() on the mapped file, 37 // so no additional member (or definition of SharedMemoryLock) is 38 // needed. 39 #endif 40 41 // Platform abstraction for shared memory. Provides a C++ wrapper 42 // around the OS primitive for a memory mapped file. 43 class BASE_API SharedMemory { 44 public: 45 SharedMemory(); 46 47 #if defined(OS_WIN) 48 // Similar to the default constructor, except that this allows for 49 // calling Lock() to acquire the named mutex before either Create or Open 50 // are called on Windows. 51 explicit SharedMemory(const std::wstring& name); 52 #endif 53 54 // Create a new SharedMemory object from an existing, open 55 // shared memory file. 56 SharedMemory(SharedMemoryHandle handle, bool read_only); 57 58 // Create a new SharedMemory object from an existing, open 59 // shared memory file that was created by a remote process and not shared 60 // to the current process. 61 SharedMemory(SharedMemoryHandle handle, bool read_only, 62 ProcessHandle process); 63 64 // Closes any open files. 65 ~SharedMemory(); 66 67 // Return true iff the given handle is valid (i.e. not the distingished 68 // invalid value; NULL for a HANDLE and -1 for a file descriptor) 69 static bool IsHandleValid(const SharedMemoryHandle& handle); 70 71 // Returns invalid handle (see comment above for exact definition). 72 static SharedMemoryHandle NULLHandle(); 73 74 // Closes a shared memory handle. 75 static void CloseHandle(const SharedMemoryHandle& handle); 76 77 // Creates and maps an anonymous shared memory segment of size size. 78 // Returns true on success and false on failure. 79 bool CreateAndMapAnonymous(uint32 size); 80 81 // Creates an anonymous shared memory segment of size size. 82 // Returns true on success and false on failure. 83 bool CreateAnonymous(uint32 size); 84 85 // Creates or opens a shared memory segment based on a name. 86 // If open_existing is true, and the shared memory already exists, 87 // opens the existing shared memory and ignores the size parameter. 88 // If open_existing is false, shared memory must not exist. 89 // size is the size of the block to be created. 90 // Returns true on success, false on failure. 91 bool CreateNamed(const std::string& name, bool open_existing, uint32 size); 92 93 // Deletes resources associated with a shared memory segment based on name. 94 // Not all platforms require this call. 95 bool Delete(const std::string& name); 96 97 // Opens a shared memory segment based on a name. 98 // If read_only is true, opens for read-only access. 99 // Returns true on success, false on failure. 100 bool Open(const std::string& name, bool read_only); 101 102 // Maps the shared memory into the caller's address space. 103 // Returns true on success, false otherwise. The memory address 104 // is accessed via the memory() accessor. 105 bool Map(uint32 bytes); 106 107 // Unmaps the shared memory from the caller's address space. 108 // Returns true if successful; returns false on error or if the 109 // memory is not mapped. 110 bool Unmap(); 111 112 // Get the size of the shared memory backing file. 113 // Note: This size is only available to the creator of the 114 // shared memory, and not to those that opened shared memory 115 // created externally. 116 // Returns 0 if not created or unknown. 117 // Deprecated method, please keep track of the size yourself if you created 118 // it. 119 // http://crbug.com/60821 120 uint32 created_size() const { return created_size_; } 121 122 // Gets a pointer to the opened memory space if it has been 123 // Mapped via Map(). Returns NULL if it is not mapped. 124 void *memory() const { return memory_; } 125 126 // Returns the underlying OS handle for this segment. 127 // Use of this handle for anything other than an opaque 128 // identifier is not portable. 129 SharedMemoryHandle handle() const; 130 131 #if defined(OS_POSIX) 132 // Returns a unique identifier for this shared memory segment. Inode numbers 133 // are technically only unique to a single filesystem. However, we always 134 // allocate shared memory backing files from the same directory, so will end 135 // up on the same filesystem. 136 SharedMemoryId id() const { return inode_; } 137 #endif 138 139 // Closes the open shared memory segment. 140 // It is safe to call Close repeatedly. 141 void Close(); 142 143 // Shares the shared memory to another process. Attempts 144 // to create a platform-specific new_handle which can be 145 // used in a remote process to access the shared memory 146 // file. new_handle is an ouput parameter to receive 147 // the handle for use in the remote process. 148 // Returns true on success, false otherwise. 149 bool ShareToProcess(ProcessHandle process, 150 SharedMemoryHandle* new_handle) { 151 return ShareToProcessCommon(process, new_handle, false); 152 } 153 154 // Logically equivalent to: 155 // bool ok = ShareToProcess(process, new_handle); 156 // Close(); 157 // return ok; 158 // Note that the memory is unmapped by calling this method, regardless of the 159 // return value. 160 bool GiveToProcess(ProcessHandle process, 161 SharedMemoryHandle* new_handle) { 162 return ShareToProcessCommon(process, new_handle, true); 163 } 164 165 // Locks the shared memory. 166 // This is a cross-process lock which may be recursively 167 // locked by the same thread. 168 // TODO(port): 169 // WARNING: on POSIX the lock only works across processes, not 170 // across threads. 2 threads in the same process can both grab the 171 // lock at the same time. There are several solutions for this 172 // (futex, lockf+anon_semaphore) but none are both clean and common 173 // across Mac and Linux. 174 void Lock(); 175 176 #if defined(OS_WIN) 177 // A Lock() implementation with a timeout that also allows setting 178 // security attributes on the mutex. sec_attr may be NULL. 179 // Returns true if the Lock() has been acquired, false if the timeout was 180 // reached. 181 bool Lock(uint32 timeout_ms, SECURITY_ATTRIBUTES* sec_attr); 182 #endif 183 184 // Releases the shared memory lock. 185 void Unlock(); 186 187 private: 188 #if defined(OS_POSIX) 189 bool PrepareMapFile(FILE *fp); 190 bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); 191 void LockOrUnlockCommon(int function); 192 #endif 193 bool ShareToProcessCommon(ProcessHandle process, 194 SharedMemoryHandle* new_handle, 195 bool close_self); 196 197 #if defined(OS_WIN) 198 std::wstring name_; 199 HANDLE mapped_file_; 200 #elif defined(OS_POSIX) 201 int mapped_file_; 202 uint32 mapped_size_; 203 ino_t inode_; 204 #endif 205 void* memory_; 206 bool read_only_; 207 uint32 created_size_; 208 #if !defined(OS_POSIX) 209 SharedMemoryLock lock_; 210 #endif 211 212 DISALLOW_COPY_AND_ASSIGN(SharedMemory); 213 }; 214 215 // A helper class that acquires the shared memory lock while 216 // the SharedMemoryAutoLock is in scope. 217 class SharedMemoryAutoLock { 218 public: 219 explicit SharedMemoryAutoLock(SharedMemory* shared_memory) 220 : shared_memory_(shared_memory) { 221 shared_memory_->Lock(); 222 } 223 224 ~SharedMemoryAutoLock() { 225 shared_memory_->Unlock(); 226 } 227 228 private: 229 SharedMemory* shared_memory_; 230 DISALLOW_COPY_AND_ASSIGN(SharedMemoryAutoLock); 231 }; 232 233 } // namespace base 234 235 #endif // BASE_SHARED_MEMORY_H_ 236