// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/memory/shared_memory_handle.h" #include #include #include #include #include "base/mac/mac_util.h" #include "base/posix/eintr_wrapper.h" namespace base { SharedMemoryHandle::SharedMemoryHandle() {} SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) { mach_port_t named_right; kern_return_t kr = mach_make_memory_entry_64( mach_task_self(), &size, 0, // Address. MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, &named_right, MACH_PORT_NULL); // Parent handle. if (kr != KERN_SUCCESS) { memory_object_ = MACH_PORT_NULL; return; } memory_object_ = named_right; size_ = size; pid_ = GetCurrentProcId(); ownership_passes_to_ipc_ = false; } SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object, mach_vm_size_t size, base::ProcessId pid) : memory_object_(memory_object), size_(size), pid_(pid), ownership_passes_to_ipc_(false) {} SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) { CopyRelevantData(handle); } SharedMemoryHandle& SharedMemoryHandle::operator=( const SharedMemoryHandle& handle) { if (this == &handle) return *this; CopyRelevantData(handle); return *this; } SharedMemoryHandle SharedMemoryHandle::Duplicate() const { if (!IsValid()) return SharedMemoryHandle(MACH_PORT_NULL, 0, 0); // Increment the ref count. kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_, MACH_PORT_RIGHT_SEND, 1); DCHECK_EQ(kr, KERN_SUCCESS); SharedMemoryHandle handle(*this); handle.SetOwnershipPassesToIPC(true); return handle; } bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { if (!IsValid() && !handle.IsValid()) return true; return memory_object_ == handle.memory_object_ && size_ == handle.size_ && pid_ == handle.pid_; } bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { return !(*this == handle); } bool SharedMemoryHandle::IsValid() const { return memory_object_ != MACH_PORT_NULL; } mach_port_t SharedMemoryHandle::GetMemoryObject() const { return memory_object_; } bool SharedMemoryHandle::GetSize(size_t* size) const { if (!IsValid()) { *size = 0; return true; } *size = size_; return true; } bool SharedMemoryHandle::MapAt(off_t offset, size_t bytes, void** memory, bool read_only) { DCHECK(IsValid()); DCHECK_EQ(pid_, GetCurrentProcId()); kern_return_t kr = mach_vm_map( mach_task_self(), reinterpret_cast(memory), // Output parameter bytes, 0, // Alignment mask VM_FLAGS_ANYWHERE, memory_object_, offset, FALSE, // Copy VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection VM_INHERIT_NONE); return kr == KERN_SUCCESS; } void SharedMemoryHandle::Close() const { if (!IsValid()) return; kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_); if (kr != KERN_SUCCESS) DPLOG(ERROR) << "Error deallocating mach port: " << kr; } void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { ownership_passes_to_ipc_ = ownership_passes; } bool SharedMemoryHandle::OwnershipPassesToIPC() const { return ownership_passes_to_ipc_; } void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) { memory_object_ = handle.memory_object_; size_ = handle.size_; pid_ = handle.pid_; ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_; } } // namespace base