Prepare for cloning address spaces, not there yet
This commit is contained in:
parent
e43777bd31
commit
1c3377fc98
@ -7,13 +7,21 @@ struct AddressSpace
|
|||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void reset();
|
void detach();
|
||||||
|
|
||||||
|
AddressSpace clone();
|
||||||
|
|
||||||
PageTable* get_pml4()
|
PageTable* get_pml4()
|
||||||
{
|
{
|
||||||
return m_pml4;
|
return m_pml4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_cloned()
|
||||||
|
{
|
||||||
|
return m_cloned;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PageTable* m_pml4;
|
PageTable* m_pml4;
|
||||||
|
bool m_cloned;
|
||||||
};
|
};
|
@ -10,7 +10,8 @@ namespace Scheduler
|
|||||||
void exit(int status);
|
void exit(int status);
|
||||||
void sleep(unsigned long ms);
|
void sleep(unsigned long ms);
|
||||||
void add_kernel_task(void (*task)(void));
|
void add_kernel_task(void (*task)(void));
|
||||||
void add_user_task(void* task);
|
|
||||||
|
Task* create_user_task();
|
||||||
|
|
||||||
void load_user_task(const char* filename);
|
void load_user_task(const char* filename);
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ AddressSpace AddressSpace::create()
|
|||||||
|
|
||||||
void AddressSpace::destroy()
|
void AddressSpace::destroy()
|
||||||
{
|
{
|
||||||
|
if (m_cloned)
|
||||||
|
{
|
||||||
|
kdbgln("Will not destroy a cloned address space, I don't own it");
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint64_t pages_freed = 0;
|
uint64_t pages_freed = 0;
|
||||||
for (int i = 0; i < 512; i++)
|
for (int i = 0; i < 512; i++)
|
||||||
{
|
{
|
||||||
@ -71,60 +76,18 @@ void AddressSpace::destroy()
|
|||||||
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
|
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressSpace::reset()
|
void AddressSpace::detach()
|
||||||
{
|
{
|
||||||
uint64_t pages_freed = 0;
|
if (!m_cloned) return;
|
||||||
for (int i = 0; i < 512; i++)
|
m_pml4 = (PageTable*)PMM::request_page();
|
||||||
{
|
|
||||||
PageDirectoryEntry& pdp_pde = m_pml4->entries[i];
|
|
||||||
if (!pdp_pde.present) continue;
|
|
||||||
if (pdp_pde.larger_pages)
|
|
||||||
{
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page((void*)pdp_pde.get_address());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PageTable* pdp = (PageTable*)pdp_pde.get_address();
|
|
||||||
for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one
|
|
||||||
{
|
|
||||||
PageDirectoryEntry& pd_pde = pdp->entries[j];
|
|
||||||
if (!pd_pde.present) continue;
|
|
||||||
if (pd_pde.larger_pages)
|
|
||||||
{
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page((void*)pd_pde.get_address());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PageTable* pd = (PageTable*)pd_pde.get_address();
|
|
||||||
for (int k = 0; k < 512; k++)
|
|
||||||
{
|
|
||||||
PageDirectoryEntry& pt_pde = pd->entries[k];
|
|
||||||
if (!pt_pde.present) continue;
|
|
||||||
if (pt_pde.larger_pages)
|
|
||||||
{
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page((void*)pt_pde.get_address());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PageTable* pt = (PageTable*)pt_pde.get_address();
|
|
||||||
for (int l = 0; l < 512; l++)
|
|
||||||
{
|
|
||||||
PageDirectoryEntry& pde = pt->entries[l];
|
|
||||||
if (!pde.present) continue;
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page((void*)pde.get_address());
|
|
||||||
}
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page(pt);
|
|
||||||
}
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page(pd);
|
|
||||||
}
|
|
||||||
pages_freed++;
|
|
||||||
PMM::free_page(pdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
VMM::install_kernel_page_directory_into_address_space(*this);
|
VMM::install_kernel_page_directory_into_address_space(*this);
|
||||||
|
m_cloned = false;
|
||||||
|
}
|
||||||
|
|
||||||
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
|
AddressSpace AddressSpace::clone()
|
||||||
|
{
|
||||||
|
AddressSpace result;
|
||||||
|
result.m_pml4 = m_pml4;
|
||||||
|
result.m_cloned = true;
|
||||||
|
return result;
|
||||||
}
|
}
|
@ -75,10 +75,6 @@ void sys_exec(Context* context, const char* pathname)
|
|||||||
|
|
||||||
// At this point, pretty much nothing can fail.
|
// At this point, pretty much nothing can fail.
|
||||||
|
|
||||||
// task->address_space.reset();
|
|
||||||
|
|
||||||
// VMM::switch_to_user_address_space(task->address_space);
|
|
||||||
|
|
||||||
ELFImage* image = ELFLoader::load_elf_from_vfs(program);
|
ELFImage* image = ELFLoader::load_elf_from_vfs(program);
|
||||||
ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly
|
ASSERT(image); // If check_elf_image succeeded, load_elf_from_vfs MUST succeed, unless something has gone terribly
|
||||||
// wrong.
|
// wrong.
|
||||||
|
@ -87,21 +87,16 @@ void Scheduler::add_kernel_task(void (*task)(void))
|
|||||||
new_task->id, new_task->regs.rsp, task_num);
|
new_task->id, new_task->regs.rsp, task_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::add_user_task(void* task)
|
Task* Scheduler::create_user_task()
|
||||||
{
|
{
|
||||||
Task* new_task = new Task;
|
Task* new_task = new Task;
|
||||||
ASSERT(new_task);
|
ASSERT(new_task);
|
||||||
memset(&new_task->regs, 0, sizeof(Context));
|
memset(&new_task->regs, 0, sizeof(Context));
|
||||||
new_task->user_task = true;
|
new_task->user_task = true;
|
||||||
new_task->id = free_tid++;
|
new_task->id = free_tid++;
|
||||||
new_task->regs.rip = (uint64_t)task;
|
|
||||||
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
|
new_task->allocated_stack = (uint64_t)MemoryManager::get_pages(
|
||||||
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
|
TASK_PAGES_IN_STACK, MAP_READ_WRITE | MAP_USER); // 16 KB is enough for everyone, right?
|
||||||
new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK);
|
new_task->regs.rsp = get_top_of_stack(new_task->allocated_stack, TASK_PAGES_IN_STACK);
|
||||||
new_task->regs.cs = 0x18 | 0x03;
|
|
||||||
new_task->regs.ss = 0x20 | 0x03;
|
|
||||||
new_task->regs.ds = 0x20 | 0x03;
|
|
||||||
new_task->regs.rflags = (1 << 21) | (1 << 9); // enable interrupts
|
|
||||||
new_task->task_sleep = 0;
|
new_task->task_sleep = 0;
|
||||||
new_task->task_time = 0;
|
new_task->task_time = 0;
|
||||||
new_task->cpu_time = 0;
|
new_task->cpu_time = 0;
|
||||||
@ -110,10 +105,7 @@ void Scheduler::add_user_task(void* task)
|
|||||||
base_task->prev_task = new_task;
|
base_task->prev_task = new_task;
|
||||||
new_task->next_task = base_task;
|
new_task->next_task = base_task;
|
||||||
end_task = new_task;
|
end_task = new_task;
|
||||||
new_task->state = new_task->Running;
|
|
||||||
task_num++;
|
task_num++;
|
||||||
kinfoln("Adding user task: starts at %lx, tid %ld, stack at %lx, total tasks: %ld", new_task->regs.rip,
|
|
||||||
new_task->id, new_task->regs.rsp, task_num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::load_user_task(const char* filename)
|
void Scheduler::load_user_task(const char* filename)
|
||||||
|
Loading…
Reference in New Issue
Block a user