mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[libj6] Make j6::thread a template for lambdas
Instead of a C-style function pointer taking `void *userdata`, let j6::thread take a lambda as its thread procedure.
This commit is contained in:
@@ -8,40 +8,75 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <j6/flags.h>
|
||||||
|
#include <j6/memutils.h>
|
||||||
#include <j6/types.h>
|
#include <j6/types.h>
|
||||||
|
#include <j6/syscalls.h>
|
||||||
|
|
||||||
namespace j6 {
|
namespace j6 {
|
||||||
|
|
||||||
|
template <typename Proc>
|
||||||
class thread
|
class thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using proc = void (*)(void *);
|
|
||||||
|
|
||||||
/// Constructor. Create a thread and its stack space, but
|
/// Constructor. Create a thread and its stack space, but
|
||||||
/// do not start executing the thread.
|
/// do not start executing the thread.
|
||||||
/// \arg p The function where the thread will begin execution
|
/// \arg p The function where the thread will begin execution
|
||||||
/// \arg stack_top The address where the top of this thread's stack should be mapped
|
/// \arg stack_top The address where the top of this thread's stack should be mapped
|
||||||
thread(proc p, uintptr_t stack_top);
|
/// \arg stack_size Size of the stack, in bytes (default 64KiB)
|
||||||
|
thread(Proc p, uintptr_t stack_top, size_t stack_size = 0x10000) :
|
||||||
|
m_stack {j6_handle_invalid},
|
||||||
|
m_thread {j6_handle_invalid},
|
||||||
|
m_stack_top {stack_top},
|
||||||
|
m_proc {p}
|
||||||
|
{
|
||||||
|
uintptr_t stack_base = stack_top - stack_size;
|
||||||
|
m_status = j6_vma_create_map(&m_stack, stack_size, stack_base, j6_vm_flag_write);
|
||||||
|
if (m_status != j6_status_ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static constexpr size_t zeros_size = 0x10;
|
||||||
|
m_stack_top -= zeros_size; // Sentinel
|
||||||
|
memset(reinterpret_cast<void*>(m_stack_top), 0, zeros_size);
|
||||||
|
}
|
||||||
|
|
||||||
/// Start executing the thread.
|
/// Start executing the thread.
|
||||||
/// \arg user Optional pointer to user data to pass to the thread proc
|
|
||||||
/// \returns j6_status_ok if the thread was successfully started.
|
/// \returns j6_status_ok if the thread was successfully started.
|
||||||
j6_status_t start(void *user = nullptr);
|
j6_status_t start()
|
||||||
|
{
|
||||||
|
if (m_status != j6_status_ok)
|
||||||
|
return m_status;
|
||||||
|
|
||||||
|
if (m_thread != j6_handle_invalid)
|
||||||
|
return j6_err_invalid_arg;
|
||||||
|
|
||||||
|
uint64_t arg0 = reinterpret_cast<uint64_t>(this);
|
||||||
|
|
||||||
|
m_status = j6_thread_create(&m_thread, 0,
|
||||||
|
m_stack_top, reinterpret_cast<uintptr_t>(init_proc),
|
||||||
|
arg0, 0);
|
||||||
|
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
/// Wait for the thread to stop executing.
|
/// Wait for the thread to stop executing.
|
||||||
void join();
|
void join() { j6_thread_join(m_thread); }
|
||||||
|
|
||||||
thread() = delete;
|
thread() = delete;
|
||||||
thread(const thread&) = delete;
|
thread(const thread&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void init_proc(thread *t, void *user);
|
static void init_proc(thread *t)
|
||||||
|
{
|
||||||
|
t->m_proc();
|
||||||
|
j6_thread_exit();
|
||||||
|
}
|
||||||
|
|
||||||
j6_status_t m_status;
|
j6_status_t m_status;
|
||||||
j6_handle_t m_stack;
|
j6_handle_t m_stack;
|
||||||
j6_handle_t m_thread;
|
j6_handle_t m_thread;
|
||||||
uintptr_t m_stack_top;
|
uintptr_t m_stack_top;
|
||||||
proc m_proc;
|
Proc m_proc;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace j6
|
} // namespace j6
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ j6 = module("j6",
|
|||||||
"syscalls.s.cog",
|
"syscalls.s.cog",
|
||||||
"sysconf.cpp.cog",
|
"sysconf.cpp.cog",
|
||||||
"syslog.cpp",
|
"syslog.cpp",
|
||||||
"thread.cpp",
|
|
||||||
],
|
],
|
||||||
public_headers = [
|
public_headers = [
|
||||||
"j6/cap_flags.h.cog",
|
"j6/cap_flags.h.cog",
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
// The kernel depends on libj6 for some shared code,
|
|
||||||
// but should not include the user-specific code.
|
|
||||||
#ifndef __j6kernel
|
|
||||||
|
|
||||||
#include <j6/errors.h>
|
|
||||||
#include <j6/flags.h>
|
|
||||||
#include <j6/memutils.h>
|
|
||||||
#include <j6/syscalls.h>
|
|
||||||
#include <j6/thread.hh>
|
|
||||||
|
|
||||||
namespace j6 {
|
|
||||||
|
|
||||||
static constexpr size_t stack_size = 0x10000;
|
|
||||||
static constexpr size_t zeros_size = 0x10;
|
|
||||||
|
|
||||||
thread::thread(thread::proc p, uintptr_t stack_top) :
|
|
||||||
m_stack {j6_handle_invalid},
|
|
||||||
m_thread {j6_handle_invalid},
|
|
||||||
m_stack_top {stack_top},
|
|
||||||
m_proc {p}
|
|
||||||
{
|
|
||||||
uintptr_t stack_base = stack_top - stack_size;
|
|
||||||
m_status = j6_vma_create_map(&m_stack, stack_size, stack_base, j6_vm_flag_write);
|
|
||||||
if (m_status != j6_status_ok)
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_stack_top -= zeros_size;
|
|
||||||
memset(reinterpret_cast<void*>(m_stack_top), 0, zeros_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
j6_status_t
|
|
||||||
thread::start(void *user)
|
|
||||||
{
|
|
||||||
if (m_status != j6_status_ok)
|
|
||||||
return m_status;
|
|
||||||
|
|
||||||
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, 0,
|
|
||||||
m_stack_top, reinterpret_cast<uintptr_t>(init_proc),
|
|
||||||
arg0, arg1);
|
|
||||||
|
|
||||||
return m_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
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
|
|
||||||
@@ -111,8 +111,8 @@ main(int argc, const char **argv)
|
|||||||
|
|
||||||
j6_log("main thread created channel");
|
j6_log("main thread created channel");
|
||||||
|
|
||||||
j6::thread child_thread {thread_proc, stack_top};
|
j6::thread child_thread {[=](){ thread_proc(chan); }, stack_top};
|
||||||
j6_status_t result = child_thread.start(chan);
|
j6_status_t result = child_thread.start();
|
||||||
if (result != j6_status_ok)
|
if (result != j6_status_ok)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user