diff --git a/scripts/bonnibel/source.py b/scripts/bonnibel/source.py index aa09673..8fbda67 100644 --- a/scripts/bonnibel/source.py +++ b/scripts/bonnibel/source.py @@ -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") diff --git a/src/libraries/j6/j6.module b/src/libraries/j6/j6.module index ba3c5e4..a6ff0b7 100644 --- a/src/libraries/j6/j6.module +++ b/src/libraries/j6/j6.module @@ -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", diff --git a/src/libraries/j6/j6/thread.hh b/src/libraries/j6/j6/thread.hh new file mode 100644 index 0000000..dd63e51 --- /dev/null +++ b/src/libraries/j6/j6/thread.hh @@ -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 +#include +#include + +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 diff --git a/src/libraries/j6/thread.cpp b/src/libraries/j6/thread.cpp new file mode 100644 index 0000000..0fd9cc3 --- /dev/null +++ b/src/libraries/j6/thread.cpp @@ -0,0 +1,50 @@ +// The kernel depends on libj6 for some shared code, +// but should not include the user-specific code. +#ifndef __j6kernel + +#include +#include +#include +#include +#include + +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(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(m_proc)); + + return m_status; +} + +} + +#endif // __j6kernel diff --git a/src/user/drv.uart/main.cpp b/src/user/drv.uart/main.cpp index 70dbd4c..ae2c846 100644 --- a/src/user/drv.uart/main.cpp +++ b/src/user/drv.uart/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -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(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(&pump_proc)); + j6::thread pump_thread {pump_proc, stack_top}; + result = pump_thread.start(); if (result != j6_status_ok) return result;