forked from Bananymous/banan-os
Kernel: Implement proper memory region splitting
Memory regions are now splitted when they get munmapped, mprotected, or mmapped with MAP_FIXED. This is used by couple of ports, and without this we were just leaking up memory or straight up crashing programs.
This commit is contained in:
@@ -232,4 +232,33 @@ namespace Kernel
|
||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> FileBackedRegion::split(size_t offset)
|
||||
{
|
||||
ASSERT(offset && offset < m_size);
|
||||
ASSERT(offset % PAGE_SIZE == 0);
|
||||
|
||||
const bool has_dirty_pages = (m_type == Type::PRIVATE);
|
||||
|
||||
BAN::Vector<paddr_t> dirty_pages;
|
||||
if (has_dirty_pages)
|
||||
{
|
||||
TRY(dirty_pages.resize(BAN::Math::div_round_up<size_t>(m_size - offset, PAGE_SIZE)));
|
||||
for (size_t i = 0; i < dirty_pages.size(); i++)
|
||||
dirty_pages[i] = m_dirty_pages[i + offset / PAGE_SIZE];
|
||||
}
|
||||
|
||||
auto* new_region = new FileBackedRegion(m_inode, m_page_table, m_offset + offset, m_size - offset, m_type, m_flags, m_status_flags);
|
||||
if (new_region == nullptr)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
new_region->m_vaddr = m_vaddr + offset;
|
||||
new_region->m_shared_data = m_shared_data;
|
||||
new_region->m_dirty_pages = BAN::move(dirty_pages);
|
||||
|
||||
m_size = offset;
|
||||
if (has_dirty_pages)
|
||||
MUST(m_dirty_pages.resize(offset / PAGE_SIZE));
|
||||
|
||||
return BAN::UniqPtr<MemoryRegion>::adopt(new_region);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,6 +82,21 @@ namespace Kernel
|
||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(result));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> MemoryBackedRegion::split(size_t offset)
|
||||
{
|
||||
ASSERT(offset && offset < m_size);
|
||||
ASSERT(offset % PAGE_SIZE == 0);
|
||||
|
||||
auto* new_region = new MemoryBackedRegion(m_page_table, m_size - offset, m_type, m_flags, m_status_flags);
|
||||
if (new_region == nullptr)
|
||||
return BAN::Error::from_errno(ENOMEM);
|
||||
new_region->m_vaddr = m_vaddr + offset;
|
||||
|
||||
m_size = offset;
|
||||
|
||||
return BAN::UniqPtr<MemoryRegion>::adopt(new_region);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> MemoryBackedRegion::copy_data_to_region(size_t offset_into_region, const uint8_t* buffer, size_t buffer_size)
|
||||
{
|
||||
ASSERT(offset_into_region + buffer_size <= m_size);
|
||||
|
||||
@@ -87,6 +87,13 @@ namespace Kernel
|
||||
return BAN::UniqPtr<MemoryRegion>(BAN::move(region));
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::UniqPtr<MemoryRegion>> SharedMemoryObject::split(size_t offset)
|
||||
{
|
||||
(void)offset;
|
||||
dwarnln("TODO: SharedMemoryObject::split");
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<bool> SharedMemoryObject::allocate_page_containing_impl(vaddr_t address, bool wants_write)
|
||||
{
|
||||
ASSERT(contains(address));
|
||||
|
||||
Reference in New Issue
Block a user