Kernel: Make AddressSpaces reference-counted

This commit is contained in:
apio 2022-10-15 17:40:33 +02:00
parent eca7227fda
commit 68403dc029
3 changed files with 22 additions and 7 deletions

View File

@ -18,10 +18,11 @@ struct AddressSpace
bool is_cloned() bool is_cloned()
{ {
return m_cloned; return *m_refs > 1;
} }
private: private:
PageTable* m_pml4; PageTable* m_pml4;
bool m_cloned;
int* m_refs;
}; };

View File

@ -4,22 +4,25 @@
#include "log/Log.h" #include "log/Log.h"
#include "memory/PMM.h" #include "memory/PMM.h"
#include "memory/VMM.h" #include "memory/VMM.h"
#include "std/stdlib.h"
#include "utils/move.h" #include "utils/move.h"
AddressSpace AddressSpace::create() AddressSpace AddressSpace::create()
{ {
AddressSpace result; AddressSpace result;
result.m_pml4 = (PageTable*)PMM::request_page(); result.m_pml4 = (PageTable*)PMM::request_page();
result.m_cloned = false; result.m_refs = (int*)kmalloc(sizeof(int));
*result.m_refs = 1;
VMM::install_kernel_page_directory_into_address_space(result); VMM::install_kernel_page_directory_into_address_space(result);
return move(result); return move(result);
} }
void AddressSpace::destroy() void AddressSpace::destroy()
{ {
if (m_cloned) if (is_cloned())
{ {
kdbgln("Will not destroy a cloned address space, I don't own it"); kdbgln("Will not destroy a cloned address space, I don't own it");
(*m_refs)--;
return; return;
} }
uint64_t pages_freed = 0; uint64_t pages_freed = 0;
@ -75,21 +78,26 @@ void AddressSpace::destroy()
pages_freed++; pages_freed++;
PMM::free_page(m_pml4); PMM::free_page(m_pml4);
kfree(m_refs);
kdbgln("Reclaimed %ld pages from address space!", pages_freed); kdbgln("Reclaimed %ld pages from address space!", pages_freed);
} }
void AddressSpace::detach() void AddressSpace::detach()
{ {
if (!m_cloned) return; if (!is_cloned()) return;
(*m_refs)--;
m_refs = (int*)kmalloc(sizeof(int));
*m_refs = 1;
m_pml4 = (PageTable*)PMM::request_page(); m_pml4 = (PageTable*)PMM::request_page();
VMM::install_kernel_page_directory_into_address_space(*this); VMM::install_kernel_page_directory_into_address_space(*this);
m_cloned = false;
} }
AddressSpace AddressSpace::clone() AddressSpace AddressSpace::clone()
{ {
AddressSpace result; AddressSpace result;
result.m_pml4 = m_pml4; result.m_pml4 = m_pml4;
result.m_cloned = true; result.m_refs = m_refs;
*m_refs = *m_refs + 1;
return result; return result;
} }

View File

@ -73,6 +73,12 @@ void sys_exec(Context* context, const char* pathname)
Task* task = Scheduler::current_task(); Task* task = Scheduler::current_task();
ASSERT(task); ASSERT(task);
if (task->address_space.is_cloned())
{
task->address_space.detach();
VMM::switch_to_user_address_space(task->address_space);
}
// At this point, pretty much nothing can fail. // At this point, pretty much nothing can fail.
ELFImage* image = ELFLoader::load_elf_from_vfs(program); ELFImage* image = ELFLoader::load_elf_from_vfs(program);