Kernel: Processes and Threads use VirtualRange memory allocations
This commit is contained in:
parent
e0479b291d
commit
0129619d9a
|
@ -8,6 +8,7 @@
|
||||||
#include <kernel/Memory/GeneralAllocator.h>
|
#include <kernel/Memory/GeneralAllocator.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/Heap.h>
|
||||||
#include <kernel/Memory/MMU.h>
|
#include <kernel/Memory/MMU.h>
|
||||||
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
#include <kernel/SpinLock.h>
|
#include <kernel/SpinLock.h>
|
||||||
#include <kernel/Terminal/TTY.h>
|
#include <kernel/Terminal/TTY.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
@ -91,7 +92,7 @@ namespace Kernel
|
||||||
BAN::ErrorOr<int> get_free_fd();
|
BAN::ErrorOr<int> get_free_fd();
|
||||||
|
|
||||||
BAN::Vector<OpenFileDescription> m_open_files;
|
BAN::Vector<OpenFileDescription> m_open_files;
|
||||||
BAN::Vector<paddr_t> m_allocated_pages;
|
BAN::Vector<VirtualRange*> m_mapped_ranges;
|
||||||
|
|
||||||
mutable RecursiveSpinLock m_lock;
|
mutable RecursiveSpinLock m_lock;
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ namespace Kernel
|
||||||
BAN::String m_working_directory;
|
BAN::String m_working_directory;
|
||||||
BAN::Vector<Thread*> m_threads;
|
BAN::Vector<Thread*> m_threads;
|
||||||
|
|
||||||
BAN::LinkedList<FixedWidthAllocator> m_fixed_width_allocators;
|
BAN::Vector<FixedWidthAllocator*> m_fixed_width_allocators;
|
||||||
GeneralAllocator* m_general_allocator;
|
GeneralAllocator* m_general_allocator;
|
||||||
|
|
||||||
MMU* m_mmu { nullptr };
|
MMU* m_mmu { nullptr };
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <BAN/NoCopyMove.h>
|
#include <BAN/NoCopyMove.h>
|
||||||
#include <BAN/RefPtr.h>
|
#include <BAN/RefPtr.h>
|
||||||
#include <kernel/Memory/Heap.h>
|
#include <kernel/Memory/VirtualRange.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ namespace Kernel
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BAN::ErrorOr<Thread*> create(entry_t, void*, Process*);
|
static BAN::ErrorOr<Thread*> create_kernel(entry_t, void*, Process*);
|
||||||
static BAN::ErrorOr<Thread*> create_userspace(uintptr_t, Process*, int, char**);
|
static BAN::ErrorOr<Thread*> create_userspace(uintptr_t, Process*, int, char**);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ namespace Kernel
|
||||||
State state() const { return m_state; }
|
State state() const { return m_state; }
|
||||||
void terminate() { m_state = State::Terminating; }
|
void terminate() { m_state = State::Terminating; }
|
||||||
|
|
||||||
uintptr_t stack_base() const { return (uintptr_t)m_stack_base; }
|
vaddr_t stack_base() const { return m_stack->vaddr(); }
|
||||||
size_t stack_size() const { return m_is_userspace ? m_userspace_stack_size : m_kernel_stack_size; }
|
size_t stack_size() const { return m_stack->size(); }
|
||||||
|
|
||||||
uintptr_t interrupt_stack_base() const { return (uintptr_t)m_interrupt_stack; }
|
vaddr_t interrupt_stack_base() const { return m_interrupt_stack ? m_interrupt_stack->vaddr() : 0; }
|
||||||
uintptr_t interrupt_stack_size() const { return m_interrupt_stack_size; }
|
size_t interrupt_stack_size() const { return m_interrupt_stack ? m_interrupt_stack->size() : 0; }
|
||||||
|
|
||||||
static Thread& current() ;
|
static Thread& current() ;
|
||||||
static pid_t current_tid();
|
static pid_t current_tid();
|
||||||
|
@ -72,17 +72,17 @@ namespace Kernel
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr size_t m_kernel_stack_size = PAGE_SIZE * 1;
|
static constexpr size_t m_kernel_stack_size = PAGE_SIZE * 1;
|
||||||
static constexpr size_t m_userspace_stack_size = PAGE_SIZE * 1;
|
static constexpr size_t m_userspace_stack_size = PAGE_SIZE * 2;
|
||||||
static constexpr size_t m_interrupt_stack_size = PAGE_SIZE;
|
static constexpr size_t m_interrupt_stack_size = PAGE_SIZE * 2;
|
||||||
vaddr_t m_interrupt_stack { 0 };
|
VirtualRange* m_interrupt_stack { nullptr };
|
||||||
vaddr_t m_stack_base { 0 };
|
VirtualRange* m_stack { nullptr };
|
||||||
uintptr_t m_rip { 0 };
|
uintptr_t m_rip { 0 };
|
||||||
uintptr_t m_rsp { 0 };
|
uintptr_t m_rsp { 0 };
|
||||||
const pid_t m_tid { 0 };
|
const pid_t m_tid { 0 };
|
||||||
State m_state { State::NotStarted };
|
State m_state { State::NotStarted };
|
||||||
Process* m_process { nullptr };
|
Process* m_process { nullptr };
|
||||||
bool m_in_syscall { false };
|
bool m_in_syscall { false };
|
||||||
bool m_is_userspace { false };
|
bool m_is_userspace { false };
|
||||||
|
|
||||||
userspace_entry_t m_userspace_entry;
|
userspace_entry_t m_userspace_entry;
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
auto* process = create_process();
|
auto* process = create_process();
|
||||||
MUST(process->m_working_directory.push_back('/'));
|
MUST(process->m_working_directory.push_back('/'));
|
||||||
auto* thread = MUST(Thread::create(entry, data, process));
|
auto* thread = MUST(Thread::create_kernel(entry, data, process));
|
||||||
process->add_thread(thread);
|
process->add_thread(thread);
|
||||||
register_process(process);
|
register_process(process);
|
||||||
return process;
|
return process;
|
||||||
|
@ -74,19 +74,14 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
// TODO: Do some relocations or map kernel to higher half?
|
// TODO: Do some relocations or map kernel to higher half?
|
||||||
ASSERT(process->mmu().is_range_free(elf_program_header.p_vaddr, elf_program_header.p_memsz));
|
ASSERT(process->mmu().is_range_free(elf_program_header.p_vaddr, elf_program_header.p_memsz));
|
||||||
|
|
||||||
MMU::flags_t flags = MMU::Flags::UserSupervisor | MMU::Flags::Present;
|
MMU::flags_t flags = MMU::Flags::UserSupervisor | MMU::Flags::Present;
|
||||||
if (elf_program_header.p_flags & LibELF::PF_W)
|
if (elf_program_header.p_flags & LibELF::PF_W)
|
||||||
flags |= MMU::Flags::ReadWrite;
|
flags |= MMU::Flags::ReadWrite;
|
||||||
size_t page_start = elf_program_header.p_vaddr / PAGE_SIZE;
|
size_t page_start = elf_program_header.p_vaddr / PAGE_SIZE;
|
||||||
size_t page_end = BAN::Math::div_round_up<size_t>(elf_program_header.p_vaddr + elf_program_header.p_memsz, PAGE_SIZE);
|
size_t page_end = BAN::Math::div_round_up<size_t>(elf_program_header.p_vaddr + elf_program_header.p_memsz, PAGE_SIZE);
|
||||||
MUST(process->m_allocated_pages.reserve(page_end - page_start + 1));
|
|
||||||
for (size_t page = page_start; page <= page_end; page++)
|
size_t page_count = page_end - page_start + 1;
|
||||||
{
|
MUST(process->m_mapped_ranges.push_back(VirtualRange::create(process->mmu(), page_start * PAGE_SIZE, page_count * PAGE_SIZE, flags)));
|
||||||
auto paddr = Heap::get().take_free_page();
|
|
||||||
MUST(process->m_allocated_pages.push_back(paddr));
|
|
||||||
process->mmu().map_page_at(paddr, page * PAGE_SIZE, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
MMUScope _(process->mmu());
|
MMUScope _(process->mmu());
|
||||||
|
@ -128,13 +123,12 @@ namespace Kernel
|
||||||
ASSERT(m_threads.empty());
|
ASSERT(m_threads.empty());
|
||||||
ASSERT(m_fixed_width_allocators.empty());
|
ASSERT(m_fixed_width_allocators.empty());
|
||||||
ASSERT(m_general_allocator == nullptr);
|
ASSERT(m_general_allocator == nullptr);
|
||||||
|
ASSERT(m_mapped_ranges.empty());
|
||||||
if (m_mmu)
|
if (m_mmu)
|
||||||
{
|
{
|
||||||
MMU::kernel().load();
|
MMU::kernel().load();
|
||||||
delete m_mmu;
|
delete m_mmu;
|
||||||
}
|
}
|
||||||
for (auto paddr : m_allocated_pages)
|
|
||||||
Heap::get().release_page(paddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Process::add_thread(Thread* thread)
|
void Process::add_thread(Thread* thread)
|
||||||
|
@ -160,6 +154,11 @@ namespace Kernel
|
||||||
for (auto& open_fd : m_open_files)
|
for (auto& open_fd : m_open_files)
|
||||||
open_fd.inode = nullptr;
|
open_fd.inode = nullptr;
|
||||||
|
|
||||||
|
// NOTE: We must unmap ranges while the mmu is still alive
|
||||||
|
for (auto* range : m_mapped_ranges)
|
||||||
|
delete range;
|
||||||
|
m_mapped_ranges.clear();
|
||||||
|
|
||||||
// NOTE: We must clear allocators while the mmu is still alive
|
// NOTE: We must clear allocators while the mmu is still alive
|
||||||
m_fixed_width_allocators.clear();
|
m_fixed_width_allocators.clear();
|
||||||
if (m_general_allocator)
|
if (m_general_allocator)
|
||||||
|
@ -169,6 +168,7 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
|
|
||||||
dprintln("process {} exit", pid());
|
dprintln("process {} exit", pid());
|
||||||
|
|
||||||
s_process_lock.lock();
|
s_process_lock.lock();
|
||||||
for (size_t i = 0; i < s_processes.size(); i++)
|
for (size_t i = 0; i < s_processes.size(); i++)
|
||||||
if (s_processes[i] == this)
|
if (s_processes[i] == this)
|
||||||
|
@ -443,19 +443,22 @@ namespace Kernel
|
||||||
|
|
||||||
bool needs_new_allocator { true };
|
bool needs_new_allocator { true };
|
||||||
|
|
||||||
for (auto& allocator : m_fixed_width_allocators)
|
for (auto* allocator : m_fixed_width_allocators)
|
||||||
{
|
{
|
||||||
if (allocator.allocation_size() == allocation_size && allocator.allocations() < allocator.max_allocations())
|
if (allocator->allocation_size() == allocation_size && allocator->allocations() < allocator->max_allocations())
|
||||||
{
|
{
|
||||||
address = allocator.allocate();
|
address = allocator->allocate();
|
||||||
needs_new_allocator = false;
|
needs_new_allocator = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needs_new_allocator)
|
if (needs_new_allocator)
|
||||||
{
|
{
|
||||||
TRY(m_fixed_width_allocators.emplace_back(mmu(), allocation_size));
|
auto* allocator = new FixedWidthAllocator(mmu(), allocation_size);
|
||||||
address = m_fixed_width_allocators.back().allocate();
|
if (allocator == nullptr)
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
TRY(m_fixed_width_allocators.push_back(allocator));
|
||||||
|
address = m_fixed_width_allocators.back()->allocate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -481,14 +484,15 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
LockGuard _(m_lock);
|
LockGuard _(m_lock);
|
||||||
|
|
||||||
for (auto it = m_fixed_width_allocators.begin(); it != m_fixed_width_allocators.end(); it++)
|
for (size_t i = 0; i < m_fixed_width_allocators.size(); i++)
|
||||||
{
|
{
|
||||||
if (it->deallocate((vaddr_t)ptr))
|
auto* allocator = m_fixed_width_allocators[i];
|
||||||
|
if (allocator->deallocate((vaddr_t)ptr))
|
||||||
{
|
{
|
||||||
// TODO: This might be too much. Maybe we should only
|
// TODO: This might be too much. Maybe we should only
|
||||||
// remove allocators when we have low memory... ?
|
// remove allocators when we have low memory... ?
|
||||||
if (it->allocations() == 0)
|
if (allocator->allocations() == 0)
|
||||||
m_fixed_width_allocators.remove(it);
|
m_fixed_width_allocators.remove(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,18 @@ namespace Kernel
|
||||||
|
|
||||||
static Scheduler* s_instance = nullptr;
|
static Scheduler* s_instance = nullptr;
|
||||||
|
|
||||||
|
static uint8_t s_temp_stack[1024];
|
||||||
|
ALWAYS_INLINE static void load_temp_stack()
|
||||||
|
{
|
||||||
|
asm volatile("movq %0, %%rsp" :: "r"(s_temp_stack + sizeof(s_temp_stack)));
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<void> Scheduler::initialize()
|
BAN::ErrorOr<void> Scheduler::initialize()
|
||||||
{
|
{
|
||||||
ASSERT(s_instance == nullptr);
|
ASSERT(s_instance == nullptr);
|
||||||
s_instance = new Scheduler();
|
s_instance = new Scheduler();
|
||||||
ASSERT(s_instance);
|
ASSERT(s_instance);
|
||||||
s_instance->m_idle_thread = TRY(Thread::create([](void*) { for (;;) asm volatile("hlt"); }, nullptr, nullptr));
|
s_instance->m_idle_thread = TRY(Thread::create_kernel([](void*) { for (;;) asm volatile("hlt"); }, nullptr, nullptr));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +117,7 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
|
BAN::ErrorOr<void> Scheduler::add_thread(Thread* thread)
|
||||||
{
|
{
|
||||||
Kernel::CriticalScope critical;
|
CriticalScope _;
|
||||||
TRY(m_active_threads.emplace_back(thread));
|
TRY(m_active_threads.emplace_back(thread));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -167,13 +173,15 @@ namespace Kernel
|
||||||
current.set_rip(rip);
|
current.set_rip(rip);
|
||||||
current.set_rsp(rsp);
|
current.set_rsp(rsp);
|
||||||
|
|
||||||
|
load_temp_stack();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::execute_current_thread()
|
void Scheduler::execute_current_thread()
|
||||||
{
|
{
|
||||||
VERIFY_CLI();
|
VERIFY_CLI();
|
||||||
|
|
||||||
Thread& current = current_thread();
|
Thread& current = current_thread();
|
||||||
|
|
||||||
if (current.has_process())
|
if (current.has_process())
|
||||||
|
@ -234,6 +242,8 @@ namespace Kernel
|
||||||
VERIFY_STI();
|
VERIFY_STI();
|
||||||
DISABLE_INTERRUPTS();
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
|
load_temp_stack();
|
||||||
|
|
||||||
ASSERT(m_current_thread);
|
ASSERT(m_current_thread);
|
||||||
|
|
||||||
Thread* thread = m_current_thread->thread;
|
Thread* thread = m_current_thread->thread;
|
||||||
|
@ -262,14 +272,16 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
DISABLE_INTERRUPTS();
|
DISABLE_INTERRUPTS();
|
||||||
|
|
||||||
pid_t pid = m_current_thread->thread->process().pid();
|
load_temp_stack();
|
||||||
|
|
||||||
remove_threads(m_blocking_threads, it->thread->process().pid() == pid);
|
Process* process = &m_current_thread->thread->process();
|
||||||
remove_threads(m_sleeping_threads, it->thread->process().pid() == pid);
|
|
||||||
remove_threads(m_active_threads, it != m_current_thread && it->thread->process().pid() == pid);
|
remove_threads(m_blocking_threads, it->thread->process().pid() == process->pid());
|
||||||
|
remove_threads(m_sleeping_threads, it->thread->process().pid() == process->pid());
|
||||||
|
remove_threads(m_active_threads, it != m_current_thread && it->thread->process().pid() == process->pid());
|
||||||
|
|
||||||
delete &m_current_thread->thread->process();
|
|
||||||
delete m_current_thread->thread;
|
delete m_current_thread->thread;
|
||||||
|
delete process;
|
||||||
remove_and_advance_current_thread();
|
remove_and_advance_current_thread();
|
||||||
execute_current_thread();
|
execute_current_thread();
|
||||||
|
|
||||||
|
|
|
@ -399,7 +399,7 @@ argument_done:
|
||||||
thread_data_t thread_data = { this, spinlock, arguments };
|
thread_data_t thread_data = { this, spinlock, arguments };
|
||||||
spinlock.lock();
|
spinlock.lock();
|
||||||
|
|
||||||
auto* thread = TRY(Thread::create(function, &thread_data, &Process::current()));
|
auto* thread = TRY(Thread::create_kernel(function, &thread_data, &Process::current()));
|
||||||
Process::current().add_thread(thread);
|
Process::current().add_thread(thread);
|
||||||
while (spinlock.is_locked());
|
while (spinlock.is_locked());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include <BAN/Errors.h>
|
#include <BAN/Errors.h>
|
||||||
#include <kernel/CriticalScope.h>
|
|
||||||
#include <kernel/InterruptController.h>
|
#include <kernel/InterruptController.h>
|
||||||
#include <kernel/Memory/kmalloc.h>
|
#include <kernel/Memory/kmalloc.h>
|
||||||
|
#include <kernel/Memory/MMUScope.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
@ -10,6 +10,7 @@ namespace Kernel
|
||||||
{
|
{
|
||||||
|
|
||||||
extern "C" void thread_userspace_trampoline(uint64_t rsp, uint64_t rip, int argc, char** argv);
|
extern "C" void thread_userspace_trampoline(uint64_t rsp, uint64_t rip, int argc, char** argv);
|
||||||
|
extern "C" uintptr_t read_rip();
|
||||||
|
|
||||||
template<size_t size, typename T>
|
template<size_t size, typename T>
|
||||||
static void write_to_stack(uintptr_t& rsp, const T& value)
|
static void write_to_stack(uintptr_t& rsp, const T& value)
|
||||||
|
@ -20,7 +21,7 @@ namespace Kernel
|
||||||
|
|
||||||
static pid_t s_next_tid = 1;
|
static pid_t s_next_tid = 1;
|
||||||
|
|
||||||
BAN::ErrorOr<Thread*> Thread::create(entry_t entry, void* data, Process* process)
|
BAN::ErrorOr<Thread*> Thread::create_kernel(entry_t entry, void* data, Process* process)
|
||||||
{
|
{
|
||||||
// Create the thread object
|
// Create the thread object
|
||||||
Thread* thread = new Thread(s_next_tid++, process);
|
Thread* thread = new Thread(s_next_tid++, process);
|
||||||
|
@ -28,11 +29,11 @@ namespace Kernel
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
|
||||||
// Initialize stack and registers
|
// Initialize stack and registers
|
||||||
thread->m_stack_base = (vaddr_t)kmalloc(m_kernel_stack_size, PAGE_SIZE);
|
thread->m_stack = VirtualRange::create_kmalloc(m_kernel_stack_size);
|
||||||
if (thread->m_stack_base == 0)
|
if (thread->m_stack == nullptr)
|
||||||
return BAN::Error::from_errno(ENOMEM);
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
thread->m_rsp = (uintptr_t)thread->m_stack_base + m_kernel_stack_size;
|
thread->m_rsp = thread->stack_base() + thread->stack_size();
|
||||||
thread->m_rip = (uintptr_t)entry;
|
thread->m_rip = (uintptr_t)entry;
|
||||||
|
|
||||||
// Initialize stack for returning
|
// Initialize stack for returning
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, thread);
|
write_to_stack<sizeof(void*)>(thread->m_rsp, thread);
|
||||||
|
@ -44,6 +45,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<Thread*> Thread::create_userspace(uintptr_t entry, Process* process, int argc, char** argv)
|
BAN::ErrorOr<Thread*> Thread::create_userspace(uintptr_t entry, Process* process, int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
ASSERT(process);
|
||||||
|
|
||||||
// Create the thread object
|
// Create the thread object
|
||||||
Thread* thread = new Thread(s_next_tid++, process);
|
Thread* thread = new Thread(s_next_tid++, process);
|
||||||
if (thread == nullptr)
|
if (thread == nullptr)
|
||||||
|
@ -51,13 +54,20 @@ namespace Kernel
|
||||||
thread->m_is_userspace = true;
|
thread->m_is_userspace = true;
|
||||||
|
|
||||||
// Allocate stack
|
// Allocate stack
|
||||||
thread->m_stack_base = (uintptr_t)kmalloc(m_userspace_stack_size, PAGE_SIZE);
|
thread->m_stack = VirtualRange::create(process->mmu(), 0, m_userspace_stack_size, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
|
||||||
ASSERT(thread->m_stack_base);
|
if (thread->m_stack == nullptr)
|
||||||
process->mmu().identity_map_range(thread->m_stack_base, m_userspace_stack_size, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
|
{
|
||||||
|
delete thread;
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate interrupt stack
|
// Allocate interrupt stack
|
||||||
thread->m_interrupt_stack = (vaddr_t)kmalloc(m_interrupt_stack_size, PAGE_SIZE);
|
thread->m_interrupt_stack = VirtualRange::create(process->mmu(), 0, m_interrupt_stack_size, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
|
||||||
ASSERT(thread->m_interrupt_stack);
|
if (thread->m_interrupt_stack == nullptr)
|
||||||
|
{
|
||||||
|
delete thread;
|
||||||
|
return BAN::Error::from_errno(ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
thread->m_userspace_entry = { .entry = entry, .argc = argc, .argv = argv };
|
thread->m_userspace_entry = { .entry = entry, .argc = argc, .argv = argv };
|
||||||
|
|
||||||
|
@ -70,13 +80,16 @@ namespace Kernel
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
thread->m_rsp = thread->m_stack_base + m_userspace_stack_size;
|
thread->m_rsp = thread->stack_base() + thread->stack_size();
|
||||||
thread->m_rip = (uintptr_t)entry_trampoline;
|
thread->m_rip = (uintptr_t)entry_trampoline;
|
||||||
|
|
||||||
// Setup stack for returning
|
// Setup stack for returning
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, thread);
|
{
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, &Thread::on_exit);
|
MMUScope _(process->mmu());
|
||||||
write_to_stack<sizeof(void*)>(thread->m_rsp, nullptr);
|
write_to_stack<sizeof(void*)>(thread->m_rsp, thread);
|
||||||
|
write_to_stack<sizeof(void*)>(thread->m_rsp, &Thread::on_exit);
|
||||||
|
write_to_stack<sizeof(void*)>(thread->m_rsp, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
@ -99,10 +112,12 @@ namespace Kernel
|
||||||
Thread::~Thread()
|
Thread::~Thread()
|
||||||
{
|
{
|
||||||
dprintln("thread {} ({}) exit", tid(), m_process->pid());
|
dprintln("thread {} ({}) exit", tid(), m_process->pid());
|
||||||
|
if (m_stack)
|
||||||
|
delete m_stack;
|
||||||
|
m_stack = nullptr;
|
||||||
if (m_interrupt_stack)
|
if (m_interrupt_stack)
|
||||||
kfree((void*)m_interrupt_stack);
|
delete m_interrupt_stack;
|
||||||
kfree((void*)m_stack_base);
|
m_interrupt_stack = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::validate_stack() const
|
void Thread::validate_stack() const
|
||||||
|
|
Loading…
Reference in New Issue