Kernel: Optimize FileBackedRegion CoW
Just copy data from the existing page instead of locking inode's shared data, copying to temporary buffer and finally copying to destination
This commit is contained in:
@@ -106,7 +106,7 @@ namespace Kernel
|
|||||||
LockGuard _(m_shared_data->mutex);
|
LockGuard _(m_shared_data->mutex);
|
||||||
for (vaddr_t page_addr = first_page; page_addr < last_page; page_addr += PAGE_SIZE)
|
for (vaddr_t page_addr = first_page; page_addr < last_page; page_addr += PAGE_SIZE)
|
||||||
if (contains(page_addr))
|
if (contains(page_addr))
|
||||||
m_shared_data->sync((page_addr - m_vaddr) / PAGE_SIZE);
|
m_shared_data->sync((m_offset + page_addr - m_vaddr) / PAGE_SIZE);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -135,17 +135,17 @@ namespace Kernel
|
|||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
const size_t offset = (vaddr - m_vaddr) + m_offset;
|
const size_t offset = (vaddr - m_vaddr) + m_offset;
|
||||||
ASSERT(offset % 4096 == 0);
|
ASSERT(offset % PAGE_SIZE == 0);
|
||||||
|
|
||||||
const size_t bytes = BAN::Math::min<size_t>(m_inode->size() - offset, PAGE_SIZE);
|
const size_t bytes = BAN::Math::min<size_t>(m_inode->size() - offset, PAGE_SIZE);
|
||||||
|
|
||||||
memset(m_shared_data->page_buffer, 0x00, PAGE_SIZE);
|
|
||||||
TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
|
TRY(m_inode->read(offset, BAN::ByteSpan(m_shared_data->page_buffer, bytes)));
|
||||||
shared_data_has_correct_page = true;
|
memset(m_shared_data->page_buffer + bytes, 0, PAGE_SIZE - bytes);
|
||||||
|
|
||||||
PageTable::with_fast_page(m_shared_data->pages[shared_page_index], [&] {
|
PageTable::with_fast_page(m_shared_data->pages[shared_page_index], [&] {
|
||||||
memcpy(PageTable::fast_page_as_ptr(), m_shared_data->page_buffer, PAGE_SIZE);
|
memcpy(PageTable::fast_page_as_ptr(), m_shared_data->page_buffer, PAGE_SIZE);
|
||||||
});
|
});
|
||||||
|
shared_data_has_correct_page = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == Type::PRIVATE && wants_write)
|
if (m_type == Type::PRIVATE && wants_write)
|
||||||
@@ -176,29 +176,17 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// page does not need remappings
|
ASSERT(m_type == Type::PRIVATE && wants_write);
|
||||||
if (m_type != Type::PRIVATE || !wants_write)
|
|
||||||
return false;
|
|
||||||
ASSERT(writable());
|
|
||||||
|
|
||||||
// page is already mapped as writable
|
|
||||||
if (m_page_table.get_page_flags(vaddr) & PageTable::Flags::ReadWrite)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const paddr_t paddr = Heap::get().take_free_page();
|
const paddr_t paddr = Heap::get().take_free_page();
|
||||||
if (paddr == 0)
|
if (paddr == 0)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
ASSERT(m_shared_data);
|
ASSERT(&m_page_table == &PageTable::current());
|
||||||
LockGuard _(m_shared_data->mutex);
|
PageTable::with_fast_page(paddr, [vaddr] {
|
||||||
ASSERT(m_shared_data->pages[shared_page_index]);
|
memcpy(PageTable::fast_page_as_ptr(), reinterpret_cast<void*>(vaddr), PAGE_SIZE);
|
||||||
|
});
|
||||||
|
|
||||||
PageTable::with_fast_page(m_shared_data->pages[shared_page_index], [&] {
|
|
||||||
memcpy(m_shared_data->page_buffer, PageTable::fast_page_as_ptr(), PAGE_SIZE);
|
|
||||||
});
|
|
||||||
PageTable::with_fast_page(paddr, [&] {
|
|
||||||
memcpy(PageTable::fast_page_as_ptr(), m_shared_data->page_buffer, PAGE_SIZE);
|
|
||||||
});
|
|
||||||
m_dirty_pages[local_page_index] = paddr;
|
m_dirty_pages[local_page_index] = paddr;
|
||||||
m_page_table.map_page_at(paddr, vaddr, m_flags);
|
m_page_table.map_page_at(paddr, vaddr, m_flags);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user