[libj6] Add thread wrapper class
This new class makes it easier for user programs to spawn threads. This change also includes support for .hh files in modules, to differentiate headers that are C++-only in system libraries.
This commit is contained in:
@@ -49,7 +49,7 @@ class ParseSource(Source):
|
||||
@property
|
||||
def gather(self):
|
||||
_, suffix = splitext(self.output)
|
||||
return suffix in (".h", ".inc")
|
||||
return suffix in (".h", ".hh", ".inc")
|
||||
|
||||
@property
|
||||
def next(self):
|
||||
@@ -113,7 +113,7 @@ def make_source(root, path):
|
||||
return CompileSource(path, root)
|
||||
elif suffix in (".cog",):
|
||||
return ParseSource(path, root)
|
||||
elif suffix in (".h", ".inc"):
|
||||
elif suffix in (".h", ".hh", ".inc"):
|
||||
return HeaderSource(path, root)
|
||||
else:
|
||||
raise RuntimeError(f"{path} has no Source type")
|
||||
|
||||
@@ -8,6 +8,7 @@ j6 = module("j6",
|
||||
"protocol_ids.cpp",
|
||||
"syscalls.s.cog",
|
||||
"sysconf.cpp.cog",
|
||||
"thread.cpp",
|
||||
],
|
||||
public_headers = [
|
||||
"j6/cap_flags.h.cog",
|
||||
@@ -18,6 +19,7 @@ j6 = module("j6",
|
||||
"j6/protocols/service_locator.h",
|
||||
"j6/syscalls.h.cog",
|
||||
"j6/sysconf.h.cog",
|
||||
"j6/thread.hh",
|
||||
"j6/types.h",
|
||||
|
||||
"j6/tables/log_areas.inc",
|
||||
|
||||
46
src/libraries/j6/j6/thread.hh
Normal file
46
src/libraries/j6/j6/thread.hh
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
/// \file thread.h
|
||||
/// High level threading interface
|
||||
|
||||
// The kernel depends on libj6 for some shared code,
|
||||
// but should not include the user-specific code.
|
||||
#ifndef __j6kernel
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <j6/types.h>
|
||||
|
||||
namespace j6 {
|
||||
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
using proc = void (*)();
|
||||
|
||||
/// Constructor. Create a thread and its stack space, but
|
||||
/// do not start executing the thread.
|
||||
/// \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
|
||||
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();
|
||||
|
||||
/// Wait for the thread to stop executing.
|
||||
void join();
|
||||
|
||||
thread() = delete;
|
||||
thread(const thread&) = delete;
|
||||
|
||||
private:
|
||||
j6_status_t m_status;
|
||||
j6_handle_t m_stack;
|
||||
j6_handle_t m_thread;
|
||||
uintptr_t m_stack_top;
|
||||
proc m_proc;
|
||||
};
|
||||
|
||||
} // namespace j6
|
||||
|
||||
#endif // __j6kernel
|
||||
50
src/libraries/j6/thread.cpp
Normal file
50
src/libraries/j6/thread.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
// The kernel depends on libj6 for some shared code,
|
||||
// but should not include the user-specific code.
|
||||
#ifndef __j6kernel
|
||||
|
||||
#include <string.h>
|
||||
#include <j6/errors.h>
|
||||
#include <j6/flags.h>
|
||||
#include <j6/syscalls.h>
|
||||
#include <j6/thread.hh>
|
||||
|
||||
extern j6_handle_t __handle_self;
|
||||
|
||||
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()
|
||||
{
|
||||
if (m_status != j6_status_ok)
|
||||
return m_status;
|
||||
|
||||
if (m_thread != j6_handle_invalid)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
m_status = j6_thread_create(&m_thread, __handle_self,
|
||||
m_stack_top, reinterpret_cast<uintptr_t>(m_proc));
|
||||
|
||||
return m_status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // __j6kernel
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <j6/protocols/service_locator.h>
|
||||
#include <j6/syscalls.h>
|
||||
#include <j6/sysconf.h>
|
||||
#include <j6/thread.hh>
|
||||
#include <j6/types.h>
|
||||
#include <util/hash.h>
|
||||
|
||||
@@ -34,7 +35,6 @@ uint8_t com2_out[out_buf_size];
|
||||
serial_port *g_com1;
|
||||
serial_port *g_com2;
|
||||
|
||||
constexpr size_t stack_size = 0x10000;
|
||||
constexpr uintptr_t stack_top = 0xf80000000;
|
||||
|
||||
int
|
||||
@@ -119,16 +119,8 @@ main(int argc, const char **argv)
|
||||
g_com1 = &com1;
|
||||
g_com2 = &com2;
|
||||
|
||||
j6_handle_t child_stack_vma = j6_handle_invalid;
|
||||
result = j6_vma_create_map(&child_stack_vma, stack_size, stack_top-stack_size, j6_vm_flag_write);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
uint64_t *sp = reinterpret_cast<uint64_t*>(stack_top - 0x10);
|
||||
sp[0] = sp[1] = 0;
|
||||
|
||||
j6_handle_t child = j6_handle_invalid;
|
||||
result = j6_thread_create(&child, __handle_self, stack_top - 0x10, reinterpret_cast<uintptr_t>(&pump_proc));
|
||||
j6::thread pump_thread {pump_proc, stack_top};
|
||||
result = pump_thread.start();
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user