[kernel] Have thread call scheduler on blocking
Instead of making every callsite that may make a thread do a blocking operation also invoke the scheduler, move that logic into thread implementation - if the thread is blocking and is the current thread, call schedule(). Related changes in this commit: - Also make exiting threads and processes call the scheduler when blocking. - Threads start blocked, and get automatically added to the scheduler's blocked list.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<uint64_t>(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;
|
||||
|
||||
Reference in New Issue
Block a user