From d4283731e4234b267fbb97d6963e3827e775af6e Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Wed, 23 Sep 2020 00:22:15 -0700 Subject: [PATCH] [kernel] Add syscall helpers Added the syscalls/helpers.h file to templatize common kobject syscall operations. Also moved most syscall implementations to using process::current() and thread::current() instead of asking the scheduler. --- src/kernel/objects/channel.h | 2 + src/kernel/objects/endpoint.h | 2 + src/kernel/objects/event.h | 2 + src/kernel/objects/process.h | 2 + src/kernel/objects/thread.h | 2 + src/kernel/objects/vm_area.h | 2 + src/kernel/syscalls/channel.cpp | 37 ++++------------- src/kernel/syscalls/endpoint.cpp | 70 ++++++-------------------------- src/kernel/syscalls/helpers.h | 40 ++++++++++++++++++ src/kernel/syscalls/process.cpp | 12 ++---- src/kernel/syscalls/system.cpp | 17 +++----- src/kernel/syscalls/thread.cpp | 34 +++++++--------- 12 files changed, 96 insertions(+), 126 deletions(-) create mode 100644 src/kernel/syscalls/helpers.h diff --git a/src/kernel/objects/channel.h b/src/kernel/objects/channel.h index d381d84..26d3529 100644 --- a/src/kernel/objects/channel.h +++ b/src/kernel/objects/channel.h @@ -14,6 +14,8 @@ public: channel(); virtual ~channel(); + static constexpr kobject::type type = kobject::type::channel; + /// Check if the channel has space for a message to be sent inline bool can_send() const { return check_signal(j6_signal_channel_can_send); } diff --git a/src/kernel/objects/endpoint.h b/src/kernel/objects/endpoint.h index 92084a9..c89436b 100644 --- a/src/kernel/objects/endpoint.h +++ b/src/kernel/objects/endpoint.h @@ -13,6 +13,8 @@ public: endpoint(); virtual ~endpoint(); + static constexpr kobject::type type = kobject::type::endpoint; + /// Close the endpoint, waking all waiting processes with an error void close(); diff --git a/src/kernel/objects/event.h b/src/kernel/objects/event.h index bb4c4a0..535fe90 100644 --- a/src/kernel/objects/event.h +++ b/src/kernel/objects/event.h @@ -10,4 +10,6 @@ class event : public: event() : kobject(type::event) {} + + static constexpr kobject::type type = kobject::type::event; }; diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index 0c00a9b..f59e4ed 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -24,6 +24,8 @@ public: /// Destructor. virtual ~process(); + static constexpr kobject::type type = kobject::type::process; + /// Get the currently executing process. static process & current(); diff --git a/src/kernel/objects/thread.h b/src/kernel/objects/thread.h index 49f6e8e..68e6257 100644 --- a/src/kernel/objects/thread.h +++ b/src/kernel/objects/thread.h @@ -50,6 +50,8 @@ public: /// Destructor virtual ~thread(); + static constexpr kobject::type type = kobject::type::thread; + /// Get the currently executing thread. static thread & current(); diff --git a/src/kernel/objects/vm_area.h b/src/kernel/objects/vm_area.h index 54157c0..c074bcb 100644 --- a/src/kernel/objects/vm_area.h +++ b/src/kernel/objects/vm_area.h @@ -38,6 +38,8 @@ public: vm_area(size_t size, vm_flags flags = vm_flags::none); virtual ~vm_area(); + static constexpr kobject::type type = kobject::type::vma; + /// Get the current virtual size of the memory area size_t size() const { return m_size; } diff --git a/src/kernel/syscalls/channel.cpp b/src/kernel/syscalls/channel.cpp index df34e28..b056c9d 100644 --- a/src/kernel/syscalls/channel.cpp +++ b/src/kernel/syscalls/channel.cpp @@ -2,60 +2,39 @@ #include "j6/types.h" #include "objects/channel.h" -#include "objects/process.h" +#include "syscalls/helpers.h" namespace syscalls { j6_status_t channel_create(j6_handle_t *handle) { - process &p = process::current(); - - channel *c = new channel; - *handle = p.add_handle(c); - + construct_handle(handle); return j6_status_ok; } j6_status_t channel_close(j6_handle_t handle) { - process &p = process::current(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::channel) - return j6_err_invalid_arg; - - p.remove_handle(handle); - channel *c = static_cast(o); + channel *c = remove_handle(handle); + if (!c) return j6_err_invalid_arg; c->close(); - return j6_status_ok; } j6_status_t channel_send(j6_handle_t handle, size_t *len, void *data) { - process &p = process::current(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::channel) - return j6_err_invalid_arg; - - channel *c = static_cast(o); + channel *c = get_handle(handle); + if (!c) return j6_err_invalid_arg; return c->enqueue(len, data); } j6_status_t channel_receive(j6_handle_t handle, size_t *len, void *data) { - process &p = process::current(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::channel) - return j6_err_invalid_arg; - - channel *c = static_cast(o); + channel *c = get_handle(handle); + if (!c) return j6_err_invalid_arg; return c->dequeue(len, data); } diff --git a/src/kernel/syscalls/endpoint.cpp b/src/kernel/syscalls/endpoint.cpp index b0befb1..80c00ee 100644 --- a/src/kernel/syscalls/endpoint.cpp +++ b/src/kernel/syscalls/endpoint.cpp @@ -3,97 +3,53 @@ #include "log.h" #include "objects/endpoint.h" -#include "objects/process.h" -#include "scheduler.h" +#include "syscalls/helpers.h" namespace syscalls { j6_status_t endpoint_create(j6_handle_t *handle) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); - - endpoint *e = new endpoint; - *handle = p.add_handle(e); - + construct_handle(handle); return j6_status_ok; } j6_status_t endpoint_close(j6_handle_t handle) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::endpoint) - return j6_err_invalid_arg; - - p.remove_handle(handle); - endpoint *e = static_cast(o); + endpoint *e = remove_handle(handle); + if (!e) return j6_err_invalid_arg; e->close(); - return j6_status_ok; } j6_status_t endpoint_send(j6_handle_t handle, size_t len, void *data) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::endpoint) - return j6_err_invalid_arg; - - endpoint *e = static_cast(o); - j6_status_t status = e->send(len, data); - return status; + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; + return e->send(len, data); } j6_status_t endpoint_receive(j6_handle_t handle, size_t *len, void *data) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); - - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::endpoint) - return j6_err_invalid_arg; - - endpoint *e = static_cast(o); - j6_status_t status = e->receive(len, data); - return status; + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; + return e->receive(len, data); } j6_status_t endpoint_sendrecv(j6_handle_t handle, size_t *len, void *data) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); + endpoint *e = get_handle(handle); + if (!e) return j6_err_invalid_arg; - kobject *o = p.lookup_handle(handle); - if (!o || o->get_type() != kobject::type::endpoint) - return j6_err_invalid_arg; - - endpoint *e = static_cast(o); j6_status_t status = e->send(*len, data); if (status != j6_status_ok) return status; - status = e->receive(len, data); - return status; + return e->receive(len, data); } } // namespace syscalls diff --git a/src/kernel/syscalls/helpers.h b/src/kernel/syscalls/helpers.h new file mode 100644 index 0000000..11cadb6 --- /dev/null +++ b/src/kernel/syscalls/helpers.h @@ -0,0 +1,40 @@ +#pragma once +/// \file syscalls/helpers.h +/// Utility functions for use in syscall handler implementations + +#include "j6/types.h" +#include "objects/process.h" + +namespace syscalls { + +template +T * construct_handle(j6_handle_t *handle, Args... args) +{ + process &p = process::current(); + T *o = new T {args...}; + *handle = p.add_handle(o); + return o; +} + +template +T * get_handle(j6_handle_t handle) +{ + process &p = process::current(); + kobject *o = p.lookup_handle(handle); + if (!o || o->get_type() != T::type) + return nullptr; + return static_cast(o); +} + +template +T * remove_handle(j6_handle_t handle) +{ + T *o = get_handle(handle); + if (o) { + process &p = process::current(); + p.remove_handle(handle); + } + return o; +} + +} diff --git a/src/kernel/syscalls/process.cpp b/src/kernel/syscalls/process.cpp index 5be2499..2a57e39 100644 --- a/src/kernel/syscalls/process.cpp +++ b/src/kernel/syscalls/process.cpp @@ -3,7 +3,6 @@ #include "log.h" #include "objects/process.h" -#include "objects/thread.h" #include "scheduler.h" namespace syscalls { @@ -11,14 +10,10 @@ namespace syscalls { j6_status_t process_koid(j6_koid_t *koid) { - if (koid == nullptr) { + if (koid == nullptr) return j6_err_invalid_arg; - } - TCB *tcb = scheduler::get().current(); - process &p = thread::from_tcb(tcb)->parent(); - - *koid = p.koid(); + *koid = process::current().koid(); return j6_status_ok; } @@ -26,8 +21,7 @@ j6_status_t process_exit(int64_t status) { auto &s = scheduler::get(); - TCB *tcb = s.current(); - process &p = thread::from_tcb(tcb)->parent(); + process &p = process::current(); log::debug(logs::syscall, "Process %llx exiting with code %d", p.koid(), status); diff --git a/src/kernel/syscalls/system.cpp b/src/kernel/syscalls/system.cpp index 4d01b46..bd832c0 100644 --- a/src/kernel/syscalls/system.cpp +++ b/src/kernel/syscalls/system.cpp @@ -2,31 +2,26 @@ #include "j6/types.h" #include "log.h" -#include "scheduler.h" +#include "objects/thread.h" namespace syscalls { j6_status_t system_log(const char *message) { - if (message == nullptr) { + if (message == nullptr) return j6_err_invalid_arg; - } - auto &s = scheduler::get(); - TCB *tcb = s.current(); - thread *th = thread::from_tcb(tcb); - log::info(logs::syscall, "Message[%llx]: %s", th->koid(), message); + thread &th = thread::current(); + log::info(logs::syscall, "Message[%llx]: %s", th.koid(), message); return j6_status_ok; } j6_status_t system_noop() { - auto &s = scheduler::get(); - TCB *tcb = s.current(); - thread *th = thread::from_tcb(tcb); - log::debug(logs::syscall, "Thread %llx called noop syscall.", th->koid()); + thread &th = thread::current(); + log::debug(logs::syscall, "Thread %llx called noop syscall.", th.koid()); return j6_status_ok; } diff --git a/src/kernel/syscalls/thread.cpp b/src/kernel/syscalls/thread.cpp index 9818be8..567b565 100644 --- a/src/kernel/syscalls/thread.cpp +++ b/src/kernel/syscalls/thread.cpp @@ -3,6 +3,7 @@ #include "log.h" #include "objects/process.h" +#include "objects/thread.h" #include "scheduler.h" namespace syscalls { @@ -10,12 +11,10 @@ namespace syscalls { j6_status_t thread_koid(j6_koid_t *koid) { - if (koid == nullptr) { + if (koid == nullptr) return j6_err_invalid_arg; - } - TCB *tcb = scheduler::get().current(); - *koid = thread::from_tcb(tcb)->koid(); + *koid = thread::current().koid(); return j6_status_ok; } @@ -23,9 +22,8 @@ j6_status_t thread_create(void *rip, j6_handle_t *handle) { scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread *parent = thread::from_tcb(tcb); - process &p = parent->parent(); + thread &parent = thread::current(); + process &p = parent.parent(); thread *child = p.create_thread(scheduler::default_priority); child->add_thunk_user(reinterpret_cast(rip)); @@ -33,7 +31,7 @@ thread_create(void *rip, j6_handle_t *handle) s.add_thread(child->tcb()); log::debug(logs::syscall, "Thread %llx spawned new thread %llx, handle %d", - parent->koid(), child->koid(), *handle); + parent.koid(), child->koid(), *handle); return j6_status_ok; } @@ -42,11 +40,9 @@ j6_status_t thread_exit(int64_t status) { auto &s = scheduler::get(); - TCB *tcb = s.current(); - thread *th = thread::from_tcb(tcb); - log::debug(logs::syscall, "Thread %llx exiting with code %d", th->koid(), status); - - th->exit(status); + thread &th = thread::current(); + log::debug(logs::syscall, "Thread %llx exiting with code %d", th.koid(), status); + th.exit(status); s.schedule(); log::error(logs::syscall, "returned to exit syscall"); @@ -57,9 +53,8 @@ j6_status_t thread_pause() { auto &s = scheduler::get(); - TCB *tcb = s.current(); - thread *th = thread::from_tcb(tcb); - th->wait_on_signals(th, -1ull); + thread &th = thread::current(); + th.wait_on_signals(&th, -1ull); s.schedule(); return j6_status_ok; } @@ -68,11 +63,10 @@ j6_status_t thread_sleep(uint64_t til) { auto &s = scheduler::get(); - TCB *tcb = s.current(); - thread *th = thread::from_tcb(tcb); - log::debug(logs::syscall, "Thread %llx sleeping until %llu", th->koid(), til); + thread &th = thread::current(); + log::debug(logs::syscall, "Thread %llx sleeping until %llu", th.koid(), til); - th->wait_on_time(til); + th.wait_on_time(til); s.schedule(); return j6_status_ok; }