summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-11-16 20:51:34 -0700
committerAndreas Kling <kling@serenityos.org>2020-11-30 13:17:02 +0100
commit6a620562cc7298c2f591a06817ff560c9ef1deac (patch)
treef163becbd40b4b4cf7058ca2ea191dec7335f1ed /Kernel/Arch
parent6cb640eebaf40acbd505bcfdb0dee8e99fb77223 (diff)
downloadserenity-6a620562cc7298c2f591a06817ff560c9ef1deac.zip
Kernel: Allow passing a thread argument for new kernel threads
This adds the ability to pass a pointer to kernel thread/process. Also add the ability to use a closure as thread function, which allows passing information to a kernel thread more easily.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/i386/CPU.cpp17
1 files changed, 15 insertions, 2 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 6df49f7acc..0de723d461 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -63,6 +63,7 @@ static GenericInterruptHandler* s_interrupt_handler[GENERIC_INTERRUPT_HANDLERS_C
extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread);
extern "C" void context_first_init(Thread* from_thread, Thread* to_thread, TrapFrame* trap);
extern "C" u32 do_init_context(Thread* thread, u32 flags);
+extern "C" void exit_kernel_thread(void);
extern "C" void pre_init_finished(void);
extern "C" void post_init_finished(void);
extern "C" void handle_interrupt(TrapFrame*);
@@ -1457,6 +1458,11 @@ asm(
" jmp common_trap_exit \n"
);
+void exit_kernel_thread(void)
+{
+ Thread::current()->exit();
+}
+
u32 Processor::init_context(Thread& thread, bool leave_crit)
{
ASSERT(is_kernel_mode());
@@ -1468,7 +1474,7 @@ u32 Processor::init_context(Thread& thread, bool leave_crit)
ASSERT(in_critical() == 1);
}
- const u32 kernel_stack_top = thread.kernel_stack_top();
+ u32 kernel_stack_top = thread.kernel_stack_top();
u32 stack_top = kernel_stack_top;
// TODO: handle NT?
@@ -1482,13 +1488,20 @@ u32 Processor::init_context(Thread& thread, bool leave_crit)
// userspace_esp and userspace_ss are not popped off by iret
// unless we're switching back to user mode
stack_top -= sizeof(RegisterState) - 2 * sizeof(u32);
+
+ // For kernel threads we'll push the thread function argument
+ // which should be in tss.esp and exit_kernel_thread as return
+ // address.
+ stack_top -= 2 * sizeof(u32);
+ *reinterpret_cast<u32*>(kernel_stack_top - 2 * sizeof(u32)) = tss.esp;
+ *reinterpret_cast<u32*>(kernel_stack_top - 3 * sizeof(u32)) = FlatPtr(&exit_kernel_thread);
} else {
stack_top -= sizeof(RegisterState);
}
// we want to end up 16-byte aligned, %esp + 4 should be aligned
stack_top -= sizeof(u32);
- *reinterpret_cast<u32*>(kernel_stack_top - 4) = 0;
+ *reinterpret_cast<u32*>(kernel_stack_top - sizeof(u32)) = 0;
// set up the stack so that after returning from thread_context_first_enter()
// we will end up either in kernel mode or user mode, depending on how the thread is set up