Home | History | Annotate | Download | only in memory
      1 // Copyright 2015 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 #include "base/memory/shared_memory_handle.h"
      6 
      7 #include <mach/mach_vm.h>
      8 #include <stddef.h>
      9 #include <sys/mman.h>
     10 #include <unistd.h>
     11 
     12 #include "base/mac/mac_util.h"
     13 #include "base/posix/eintr_wrapper.h"
     14 
     15 namespace base {
     16 
     17 SharedMemoryHandle::SharedMemoryHandle() {}
     18 
     19 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) {
     20   mach_port_t named_right;
     21   kern_return_t kr = mach_make_memory_entry_64(
     22       mach_task_self(),
     23       &size,
     24       0,  // Address.
     25       MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE,
     26       &named_right,
     27       MACH_PORT_NULL);  // Parent handle.
     28   if (kr != KERN_SUCCESS) {
     29     memory_object_ = MACH_PORT_NULL;
     30     return;
     31   }
     32 
     33   memory_object_ = named_right;
     34   size_ = size;
     35   pid_ = GetCurrentProcId();
     36   ownership_passes_to_ipc_ = false;
     37 }
     38 
     39 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object,
     40                                        mach_vm_size_t size,
     41                                        base::ProcessId pid)
     42     : memory_object_(memory_object),
     43       size_(size),
     44       pid_(pid),
     45       ownership_passes_to_ipc_(false) {}
     46 
     47 SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) {
     48   CopyRelevantData(handle);
     49 }
     50 
     51 SharedMemoryHandle& SharedMemoryHandle::operator=(
     52     const SharedMemoryHandle& handle) {
     53   if (this == &handle)
     54     return *this;
     55 
     56   CopyRelevantData(handle);
     57   return *this;
     58 }
     59 
     60 SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
     61   if (!IsValid())
     62     return SharedMemoryHandle(MACH_PORT_NULL, 0, 0);
     63 
     64   // Increment the ref count.
     65   kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
     66                                         MACH_PORT_RIGHT_SEND, 1);
     67   DCHECK_EQ(kr, KERN_SUCCESS);
     68   SharedMemoryHandle handle(*this);
     69   handle.SetOwnershipPassesToIPC(true);
     70   return handle;
     71 }
     72 
     73 bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const {
     74   if (!IsValid() && !handle.IsValid())
     75     return true;
     76 
     77   return memory_object_ == handle.memory_object_ && size_ == handle.size_ &&
     78          pid_ == handle.pid_;
     79 }
     80 
     81 bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const {
     82   return !(*this == handle);
     83 }
     84 
     85 bool SharedMemoryHandle::IsValid() const {
     86   return memory_object_ != MACH_PORT_NULL;
     87 }
     88 
     89 mach_port_t SharedMemoryHandle::GetMemoryObject() const {
     90   return memory_object_;
     91 }
     92 
     93 bool SharedMemoryHandle::GetSize(size_t* size) const {
     94   if (!IsValid()) {
     95     *size = 0;
     96     return true;
     97   }
     98 
     99   *size = size_;
    100   return true;
    101 }
    102 
    103 bool SharedMemoryHandle::MapAt(off_t offset,
    104                                size_t bytes,
    105                                void** memory,
    106                                bool read_only) {
    107   DCHECK(IsValid());
    108   DCHECK_EQ(pid_, GetCurrentProcId());
    109   kern_return_t kr = mach_vm_map(
    110       mach_task_self(),
    111       reinterpret_cast<mach_vm_address_t*>(memory),  // Output parameter
    112       bytes,
    113       0,  // Alignment mask
    114       VM_FLAGS_ANYWHERE, memory_object_, offset,
    115       FALSE,                                           // Copy
    116       VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE),  // Current protection
    117       VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK,  // Maximum protection
    118       VM_INHERIT_NONE);
    119   return kr == KERN_SUCCESS;
    120 }
    121 
    122 void SharedMemoryHandle::Close() const {
    123   if (!IsValid())
    124     return;
    125 
    126   kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
    127   if (kr != KERN_SUCCESS)
    128     DPLOG(ERROR) << "Error deallocating mach port: " << kr;
    129 }
    130 
    131 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
    132   ownership_passes_to_ipc_ = ownership_passes;
    133 }
    134 
    135 bool SharedMemoryHandle::OwnershipPassesToIPC() const {
    136   return ownership_passes_to_ipc_;
    137 }
    138 
    139 void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) {
    140   memory_object_ = handle.memory_object_;
    141   size_ = handle.size_;
    142   pid_ = handle.pid_;
    143   ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_;
    144 }
    145 
    146 }  // namespace base
    147