[kernel] Give threads initial arguments
This commit changes the add_user_thunk to point to a new routine, initialize_user_cpu, which sets all the registers that were previously unset when starting a new user thread. The values for rdi and rsi are popped off the initial stack values that add_user_thunk sets up, so that user thread procs can take up to two arguments. To suppor this, j6_thread_create gained two new arguments, which are passed on to the thread. This also let me finally get rid of the hack of passing an argument in rsp when starting init.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
/// \file thread.h
|
||||
/// \file thread.hh
|
||||
/// High level threading interface
|
||||
|
||||
// The kernel depends on libj6 for some shared code,
|
||||
@@ -15,7 +15,7 @@ namespace j6 {
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
using proc = void (*)();
|
||||
using proc = void (*)(void *);
|
||||
|
||||
/// Constructor. Create a thread and its stack space, but
|
||||
/// do not start executing the thread.
|
||||
@@ -24,8 +24,9 @@ public:
|
||||
thread(proc p, uintptr_t stack_top);
|
||||
|
||||
/// Start executing the thread.
|
||||
/// \returns j6_status_ok if the thread was successfully started.
|
||||
j6_status_t start();
|
||||
/// \arg user Optional pointer to user data to pass to the thread proc
|
||||
/// \returns j6_status_ok if the thread was successfully started.
|
||||
j6_status_t start(void *user = nullptr);
|
||||
|
||||
/// Wait for the thread to stop executing.
|
||||
void join();
|
||||
@@ -34,6 +35,8 @@ public:
|
||||
thread(const thread&) = delete;
|
||||
|
||||
private:
|
||||
static void init_proc(thread *t, void *user);
|
||||
|
||||
j6_status_t m_status;
|
||||
j6_handle_t m_stack;
|
||||
j6_handle_t m_thread;
|
||||
|
||||
@@ -31,7 +31,7 @@ thread::thread(thread::proc p, uintptr_t stack_top) :
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread::start()
|
||||
thread::start(void *user)
|
||||
{
|
||||
if (m_status != j6_status_ok)
|
||||
return m_status;
|
||||
@@ -39,8 +39,12 @@ thread::start()
|
||||
if (m_thread != j6_handle_invalid)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
uint64_t arg0 = reinterpret_cast<uint64_t>(this);
|
||||
uint64_t arg1 = reinterpret_cast<uint64_t>(user);
|
||||
|
||||
m_status = j6_thread_create(&m_thread, __handle_self,
|
||||
m_stack_top, reinterpret_cast<uintptr_t>(m_proc));
|
||||
m_stack_top, reinterpret_cast<uintptr_t>(init_proc),
|
||||
arg0, arg1);
|
||||
|
||||
return m_status;
|
||||
}
|
||||
@@ -51,6 +55,13 @@ thread::join()
|
||||
j6_thread_join(m_thread);
|
||||
}
|
||||
|
||||
void
|
||||
thread::init_proc(thread *t, void *user)
|
||||
{
|
||||
t->m_proc(user);
|
||||
j6_thread_exit();
|
||||
}
|
||||
|
||||
} // namespace j6
|
||||
|
||||
#endif // __j6kernel
|
||||
|
||||
Reference in New Issue
Block a user