Home | History | Annotate | Download | only in memory
      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