diff --git a/src/kernel/objects/endpoint.cpp b/src/kernel/objects/endpoint.cpp index 4b5f9aa..e3a2840 100644 --- a/src/kernel/objects/endpoint.cpp +++ b/src/kernel/objects/endpoint.cpp @@ -1,7 +1,6 @@ #include "objects/endpoint.h" #include "objects/process.h" #include "objects/thread.h" -#include "scheduler.h" #include "vm_space.h" endpoint::endpoint() : @@ -25,16 +24,13 @@ endpoint::close() j6_status_t endpoint::send(size_t len, void *data) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread_data sender = { thread::from_tcb(tcb), data }; + thread_data sender = { &thread::current(), data }; sender.len = len; if (!check_signal(j6_signal_endpoint_can_send)) { assert_signal(j6_signal_endpoint_can_recv); - sender.th->wait_on_object(this); m_blocked.append(sender); - s.schedule(); + sender.th->wait_on_object(this); // we woke up having already finished the send // because it happened in the receiver @@ -54,16 +50,13 @@ endpoint::send(size_t len, void *data) j6_status_t endpoint::receive(size_t *len, void *data) { - scheduler &s = scheduler::get(); - TCB *tcb = s.current(); - thread_data receiver = { thread::from_tcb(tcb), data }; + thread_data receiver = { &thread::current(), data }; receiver.len_p = len; if (!check_signal(j6_signal_endpoint_can_recv)) { assert_signal(j6_signal_endpoint_can_send); - receiver.th->wait_on_object(this); m_blocked.append(receiver); - s.schedule(); + receiver.th->wait_on_object(this); // we woke up having already finished the recv // because it happened in the sender diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index 243ff55..cc61d6f 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -5,6 +5,7 @@ #include "objects/process.h" #include "objects/thread.h" #include "objects/vm_area.h" +#include "scheduler.h" // This object is initialized _before_ global constructors are called, // so we don't want it to have a global constructor at all, lest it @@ -62,6 +63,9 @@ process::exit(unsigned code) } m_return_code = code; assert_signal(j6_signal_process_exit); + + if (this == bsp_cpu_data.p) + scheduler::get().schedule(); } void @@ -90,6 +94,9 @@ process::update() thread * process::create_thread(uint8_t priority, bool user) { + if (priority == default_pri) + priority = scheduler::default_priority; + thread *th = new thread(*this, priority); kassert(th, "Failed to create thread!"); @@ -104,6 +111,7 @@ process::create_thread(uint8_t priority, bool user) } m_threads.append(th); + scheduler::get().add_thread(th->tcb()); return th; } diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index f59e4ed..fb7d2eb 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -18,6 +18,9 @@ public: /// Size of userspace thread stacks constexpr static size_t stack_size = 0x4000; + /// Value that represents default priority + constexpr static uint8_t default_pri = 0xff; + /// Constructor. process(); @@ -43,7 +46,7 @@ public: /// \args priority The new thread's scheduling priority /// \args user If true, create a userspace stack for this thread /// \returns The newly created thread object - thread * create_thread(uint8_t priorty, bool user = true); + thread * create_thread(uint8_t priorty = default_pri, bool user = true); /// Start tracking an object with a handle. /// \args obj The object this handle refers to diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index a73af25..8c3528d 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -26,8 +26,6 @@ thread::thread(process &parent, uint8_t pri, uintptr_t rsp0) : setup_kernel_stack(); else m_tcb.rsp0 = rsp0; - - set_state(state::ready); } thread::~thread() @@ -49,12 +47,16 @@ thread::current() return *bsp_cpu_data.t; } +inline void schedule_if_current(thread *t) { if (t == bsp_cpu_data.t) scheduler::get().schedule(); } + void thread::wait_on_signals(kobject *obj, j6_signal_t signals) { m_wait_type = wait_type::signal; m_wait_data = signals; clear_state(state::ready); + + schedule_if_current(this); } void @@ -63,6 +65,8 @@ thread::wait_on_time(uint64_t t) m_wait_type = wait_type::time; m_wait_data = t; clear_state(state::ready); + + schedule_if_current(this); } void @@ -71,6 +75,8 @@ thread::wait_on_object(kobject *o) m_wait_type = wait_type::object; m_wait_data = reinterpret_cast(o); clear_state(state::ready); + + schedule_if_current(this); } bool @@ -134,6 +140,8 @@ thread::exit(uint32_t code) set_state(state::exited); clear_state(state::ready); assert_signal(j6_signal_thread_exit); + + schedule_if_current(this); } void @@ -200,7 +208,8 @@ thread * thread::create_idle_thread(process &kernel, uint8_t pri, uintptr_t rsp0) { thread *idle = new thread(kernel, pri, rsp0); - idle->set_state(thread::state::constant); + idle->set_state(state::constant); + idle->set_state(state::ready); log::info(logs::task, "Created idle thread as koid %llx", idle->koid()); return idle; diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 2caf91d..8979136 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -141,13 +141,14 @@ scheduler::create_process(bool user) { process *p = new process; thread *th = p->create_thread(default_priority, user); - auto *tcb = th->tcb(); + auto *tcb = th->tcb(); tcb->time_left = quantum(default_priority); log::debug(logs::task, "Creating thread %llx, priority %d, time slice %d", th->koid(), tcb->priority, tcb->time_left); + th->set_state(thread::state::ready); return th; } @@ -183,8 +184,6 @@ scheduler::load_process(const char *name, const void *data, size_t size) tcb->rsp3 = process::stacks_top; - m_runlists[default_priority].push_back(tcb); - log::debug(logs::task, "Loading thread %s: koid %llx pri %d", name, th->koid(), tcb->priority); log::debug(logs::task, " RSP %016lx", tcb->rsp); log::debug(logs::task, " RSP0 %016lx", tcb->rsp0); @@ -203,7 +202,7 @@ scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant) if (constant) th->set_state(thread::state::constant); - m_runlists[priority].push_back(tcb); + th->set_state(thread::state::ready); log::debug(logs::task, "Creating kernel task: thread %llx pri %d", th->koid(), tcb->priority); log::debug(logs::task, " RSP0 %016lx", tcb->rsp0); @@ -247,7 +246,6 @@ void scheduler::prune(uint64_t now) if (!exited && !ready) continue; - if (exited) { // If the current thread has exited, wait until the next call // to prune() to delete it, because we may be deleting our current diff --git a/src/kernel/scheduler.h b/src/kernel/scheduler.h index 2551148..c6fa4b6 100644 --- a/src/kernel/scheduler.h +++ b/src/kernel/scheduler.h @@ -69,7 +69,7 @@ public: /// \returns A pointer to the current thread's TCB inline TCB * current() { return m_current; } - inline void add_thread(TCB *t) { m_runlists[t->priority].push_back(static_cast(t)); } + inline void add_thread(TCB *t) { m_blocked.push_back(static_cast(t)); } /// Get a reference to the system scheduler /// \returns A reference to the global system scheduler diff --git a/src/kernel/syscalls/object.cpp b/src/kernel/syscalls/object.cpp index a7ee587..fcdf7cb 100644 --- a/src/kernel/syscalls/object.cpp +++ b/src/kernel/syscalls/object.cpp @@ -5,14 +5,12 @@ #include "log.h" #include "objects/process.h" #include "objects/thread.h" -#include "scheduler.h" namespace syscalls { j6_status_t object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs) { - scheduler &s = scheduler::get(); thread &th = thread::current(); process &p = process::current(); @@ -28,7 +26,6 @@ object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs) obj->add_blocked_thread(&th); th.wait_on_signals(obj, mask); - s.schedule(); j6_status_t result = th.get_wait_result(); if (result == j6_status_ok) { diff --git a/src/kernel/syscalls/process.cpp b/src/kernel/syscalls/process.cpp index 2a57e39..3cf1884 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 "scheduler.h" namespace syscalls { @@ -20,13 +19,10 @@ process_koid(j6_koid_t *koid) j6_status_t process_exit(int64_t status) { - auto &s = scheduler::get(); process &p = process::current(); - log::debug(logs::syscall, "Process %llx exiting with code %d", p.koid(), status); p.exit(status); - s.schedule(); log::error(logs::syscall, "returned to exit syscall"); return j6_err_unexpected; diff --git a/src/kernel/syscalls/thread.cpp b/src/kernel/syscalls/thread.cpp index 567b565..0b2f859 100644 --- a/src/kernel/syscalls/thread.cpp +++ b/src/kernel/syscalls/thread.cpp @@ -4,7 +4,6 @@ #include "log.h" #include "objects/process.h" #include "objects/thread.h" -#include "scheduler.h" namespace syscalls { @@ -21,14 +20,14 @@ thread_koid(j6_koid_t *koid) j6_status_t thread_create(void *rip, j6_handle_t *handle) { - scheduler &s = scheduler::get(); thread &parent = thread::current(); process &p = parent.parent(); - thread *child = p.create_thread(scheduler::default_priority); + thread *child = p.create_thread(); child->add_thunk_user(reinterpret_cast(rip)); *handle = p.add_handle(child); - s.add_thread(child->tcb()); + child->clear_state(thread::state::loading); + child->set_state(thread::state::ready); log::debug(logs::syscall, "Thread %llx spawned new thread %llx, handle %d", parent.koid(), child->koid(), *handle); @@ -39,11 +38,9 @@ thread_create(void *rip, j6_handle_t *handle) j6_status_t thread_exit(int64_t status) { - auto &s = scheduler::get(); 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"); return j6_err_unexpected; @@ -52,22 +49,18 @@ thread_exit(int64_t status) j6_status_t thread_pause() { - auto &s = scheduler::get(); thread &th = thread::current(); th.wait_on_signals(&th, -1ull); - s.schedule(); return j6_status_ok; } j6_status_t thread_sleep(uint64_t til) { - auto &s = scheduler::get(); thread &th = thread::current(); log::debug(logs::syscall, "Thread %llx sleeping until %llu", th.koid(), til); th.wait_on_time(til); - s.schedule(); return j6_status_ok; }