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