bool SharedMemory::createHandle(Handle& handle, Protection protection) { ASSERT(!handle.m_port); ASSERT(!handle.m_size); mach_vm_address_t address = toVMAddress(m_data); memory_object_size_t size = round_page(m_size); mach_port_t port; if (protection == ReadWrite && m_port) { // Just re-use the port we have. port = m_port; if (mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_SEND, 1) != KERN_SUCCESS) return false; } else { // Create a mach port that represents the shared memory. kern_return_t kr = mach_make_memory_entry_64(mach_task_self(), &size, address, machProtection(protection), &port, MACH_PORT_NULL); if (kr != KERN_SUCCESS) return false; ASSERT(size >= round_page(m_size)); } handle.m_port = port; handle.m_size = size; return true; }
SharedMemory::~SharedMemory() { if (m_data) { kern_return_t kr = mach_vm_deallocate(mach_task_self(), toVMAddress(m_data), round_page(m_size)); #if RELEASE_LOG_DISABLED ASSERT_UNUSED(kr, kr == KERN_SUCCESS); #else if (kr != KERN_SUCCESS) { RELEASE_LOG_ERROR(VirtualMemory, "%p - SharedMemory::~SharedMemory: Failed to deallocate shared memory. %{public}s (%x)", this, mach_error_string(kr), kr); ASSERT_NOT_REACHED(); } #endif } if (m_port) { kern_return_t kr = mach_port_deallocate(mach_task_self(), m_port); #if RELEASE_LOG_DISABLED ASSERT_UNUSED(kr, kr == KERN_SUCCESS); #else if (kr != KERN_SUCCESS) { RELEASE_LOG_ERROR(VirtualMemory, "%p - SharedMemory::~SharedMemory: Failed to deallocate port. %{public}s (%x)", this, mach_error_string(kr), kr); ASSERT_NOT_REACHED(); } #endif } }
SharedMemory::~SharedMemory() { if (!m_data) return; kern_return_t kr = mach_vm_deallocate(mach_task_self(), toVMAddress(m_data), round_page(m_size)); ASSERT_UNUSED(kr, kr == KERN_SUCCESS); }
WebCore::MachSendRight SharedMemory::createSendRight(Protection protection) const { ASSERT(m_protection == protection || m_protection == Protection::ReadWrite && protection == Protection::ReadOnly); ASSERT(!!m_data ^ !!m_port); if (m_port && m_protection == protection) return WebCore::MachSendRight::create(m_port); ASSERT(m_data); return makeMemoryEntry(m_size, toVMAddress(m_data), protection, MACH_PORT_NULL); }
SharedMemory::~SharedMemory() { if (m_data && m_shouldVMDeallocateData) { kern_return_t kr = mach_vm_deallocate(mach_task_self(), toVMAddress(m_data), round_page(m_size)); ASSERT_UNUSED(kr, kr == KERN_SUCCESS); } if (m_port) { kern_return_t kr = mach_port_deallocate(mach_task_self(), m_port); ASSERT_UNUSED(kr, kr == KERN_SUCCESS); } }
RefPtr<SharedMemory> SharedMemory::create(void* data, size_t size, Protection protection) { ASSERT(size); auto sendRight = makeMemoryEntry(size, toVMAddress(data), protection, MACH_PORT_NULL); if (!sendRight) return nullptr; auto sharedMemory(adoptRef(*new SharedMemory)); sharedMemory->m_size = size; sharedMemory->m_data = nullptr; sharedMemory->m_port = sendRight.leakSendRight(); sharedMemory->m_protection = protection; return WTFMove(sharedMemory); }
bool SharedMemory::createHandle(Handle& handle, Protection protection) { ASSERT(!handle.m_port); ASSERT(!handle.m_size); mach_vm_address_t address = toVMAddress(m_data); memory_object_size_t size = round_page(m_size); // Create a mach port that represents the shared memory. mach_port_t port; kern_return_t kr = mach_make_memory_entry_64(mach_task_self(), &size, address, machProtection(protection), &port, MACH_PORT_NULL); if (kr != KERN_SUCCESS) return false; handle.m_port = port; handle.m_size = size; return true; }
PassRefPtr<SharedMemory> SharedMemory::createWithVMCopy(void* data, size_t size) { ASSERT(size); mach_vm_address_t address; kern_return_t kr = mach_vm_allocate(mach_task_self(), &address, round_page(size), VM_FLAGS_ANYWHERE); if (kr != KERN_SUCCESS) { LOG_ERROR("Failed to allocate mach_vm_allocate shared memory (%zu bytes). %s (%x)", size, mach_error_string(kr), kr); return 0; } if (data) { kr = mach_vm_copy(mach_task_self(), toVMAddress(data), round_page(size), address); if (kr != KERN_SUCCESS) { LOG_ERROR("Failed to vm_copy in to shared memory (%zu bytes). %s (%x)", size, mach_error_string(kr), kr); mach_vm_deallocate(mach_task_self(), address, round_page(size)); return 0; } } // Create a Mach port that represents the shared memory. mach_port_t port; memory_object_size_t memoryObjectSize = round_page(size); kr = mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, address, VM_PROT_DEFAULT, &port, MACH_PORT_NULL); if (kr != KERN_SUCCESS) { LOG_ERROR("Failed to create a mach port for shared memory. %s (%x)", mach_error_string(kr), kr); mach_vm_deallocate(mach_task_self(), address, round_page(size)); return 0; } ASSERT(memoryObjectSize >= round_page(size)); RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory)); sharedMemory->m_size = size; sharedMemory->m_data = toPointer(address); sharedMemory->m_port = port; return sharedMemory.release(); }
PassRefPtr<SharedMemory> SharedMemory::createFromVMBuffer(void* data, size_t size) { ASSERT(size); // Create a Mach port that represents the shared memory. mach_port_t port; memory_object_size_t memoryObjectSize = round_page(size); kern_return_t kr = mach_make_memory_entry_64(mach_task_self(), &memoryObjectSize, toVMAddress(data), VM_PROT_DEFAULT | VM_PROT_IS_MASK, &port, MACH_PORT_NULL); if (kr != KERN_SUCCESS) { LOG_ERROR("Failed to create a mach port for shared memory. %s (%x)", mach_error_string(kr), kr); return 0; } ASSERT(memoryObjectSize >= round_page(size)); if (memoryObjectSize < round_page(size)) { mach_port_deallocate(mach_task_self(), port); return 0; } RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory)); sharedMemory->m_size = size; sharedMemory->m_data = data; sharedMemory->m_shouldVMDeallocateData = false; sharedMemory->m_port = port; return sharedMemory.release(); }