mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Make page_manager::unmap_pages() handle multiple blocks
This commit is contained in:
@@ -28,7 +28,7 @@ page_block::list_append(page_block *list)
|
||||
}
|
||||
|
||||
page_block *
|
||||
page_block::list_insert(page_block *block)
|
||||
page_block::list_insert_physical(page_block *block)
|
||||
{
|
||||
page_block *cur = this;
|
||||
page_block **prev = nullptr;
|
||||
@@ -45,6 +45,24 @@ page_block::list_insert(page_block *block)
|
||||
return block;
|
||||
}
|
||||
|
||||
page_block *
|
||||
page_block::list_insert_virtual(page_block *block)
|
||||
{
|
||||
page_block *cur = this;
|
||||
page_block **prev = nullptr;
|
||||
while (cur->virtual_address < block->virtual_address) {
|
||||
prev = &cur->next;
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
block->next = cur;
|
||||
if (prev) {
|
||||
*prev = block;
|
||||
return this;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
page_block *
|
||||
page_block::list_consolidate()
|
||||
{
|
||||
@@ -219,30 +237,53 @@ page_manager::unmap_pages(uint64_t address, unsigned count)
|
||||
|
||||
kassert(cur, "Couldn't find existing mapped pages to unmap");
|
||||
|
||||
uint64_t leading = address - cur->virtual_address;
|
||||
uint64_t trailing = cur->virtual_end() - (address + page_size*count);
|
||||
uint64_t end = address + page_size * count;
|
||||
|
||||
if (leading) {
|
||||
page_block *lead_block = get_block();
|
||||
lead_block->copy(cur);
|
||||
lead_block->next = cur;
|
||||
lead_block->count = leading / page_size;
|
||||
*prev = lead_block;
|
||||
prev = &lead_block->next;
|
||||
while (cur && cur->contains(address)) {
|
||||
uint64_t leading = address - cur->virtual_address;
|
||||
uint64_t trailing =
|
||||
end > cur->virtual_end() ?
|
||||
0 : (cur->virtual_end() - end);
|
||||
|
||||
if (leading) {
|
||||
uint64_t pages = leading / page_size;
|
||||
|
||||
page_block *lead_block = get_block();
|
||||
lead_block->copy(cur);
|
||||
lead_block->next = cur;
|
||||
lead_block->count = pages;
|
||||
|
||||
cur->count -= pages;
|
||||
cur->physical_address += leading;
|
||||
cur->virtual_address += leading;
|
||||
|
||||
*prev = lead_block;
|
||||
prev = &lead_block->next;
|
||||
}
|
||||
|
||||
if (trailing) {
|
||||
uint64_t pages = trailing / page_size;
|
||||
|
||||
page_block *trail_block = get_block();
|
||||
trail_block->copy(cur);
|
||||
trail_block->next = cur->next;
|
||||
trail_block->count = pages;
|
||||
|
||||
cur->count -= pages;
|
||||
|
||||
cur->next = trail_block;
|
||||
}
|
||||
|
||||
address += cur->count * page_size;
|
||||
page_block *next = cur->next;
|
||||
|
||||
*prev = cur->next;
|
||||
cur->next = nullptr;
|
||||
cur->flags = cur->flags & ~(page_block_flags::used | page_block_flags::mapped);
|
||||
m_free->list_insert_physical(cur);
|
||||
|
||||
cur = next;
|
||||
}
|
||||
|
||||
if (trailing) {
|
||||
page_block *trail_block = get_block();
|
||||
trail_block->copy(cur);
|
||||
trail_block->next = cur->next;
|
||||
trail_block->count = trailing / page_size;
|
||||
cur->next = trail_block;
|
||||
}
|
||||
|
||||
*prev = cur->next;
|
||||
cur->next = nullptr;
|
||||
cur->flags = cur->flags & ~(page_block_flags::used | page_block_flags::mapped);
|
||||
m_free->list_insert(cur);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -93,6 +93,7 @@ struct page_block
|
||||
inline bool has_flag(page_block_flags f) const { return bitfield_contains(flags, f); }
|
||||
inline uint64_t physical_end() const { return physical_address + (count * page_manager::page_size); }
|
||||
inline uint64_t virtual_end() const { return virtual_address + (count * page_manager::page_size); }
|
||||
|
||||
inline bool contains(uint64_t vaddr) const { return vaddr >= virtual_address && vaddr < virtual_end(); }
|
||||
|
||||
/// Helper to zero out a block and optionally set the next pointer.
|
||||
@@ -115,10 +116,15 @@ struct page_block
|
||||
/// \arg list The list to append to the current list
|
||||
void list_append(page_block *list);
|
||||
|
||||
/// Sorted-insert of a block into the list.
|
||||
/// Sorted-insert of a block into the list by physical address.
|
||||
/// \arg block The single block to insert
|
||||
/// \returns The new list head
|
||||
page_block * list_insert(page_block *block);
|
||||
page_block * list_insert_physical(page_block *block);
|
||||
|
||||
/// Sorted-insert of a block into the list by virtual address.
|
||||
/// \arg block The single block to insert
|
||||
/// \returns The new list head
|
||||
page_block * list_insert_virtual(page_block *block);
|
||||
|
||||
/// Traverse the list, joining adjacent blocks where possible.
|
||||
/// \returns A linked list of freed page_block structures.
|
||||
|
||||
Reference in New Issue
Block a user