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