forked from Bananymous/banan-os
Kernel: Threads cannot take arguments anymore
This commit is contained in:
@@ -7,7 +7,7 @@ namespace Kernel
|
||||
|
||||
static Scheduler* s_instance = nullptr;
|
||||
|
||||
extern "C" void start_thread(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t rsp, uintptr_t rip);
|
||||
extern "C" void start_thread(const BAN::Function<void()>* function, uintptr_t rsp, uintptr_t rip);
|
||||
extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip);
|
||||
extern "C" uintptr_t read_rip();
|
||||
|
||||
@@ -30,6 +30,18 @@ namespace Kernel
|
||||
return *m_current_iterator;
|
||||
}
|
||||
|
||||
|
||||
BAN::ErrorOr<void> Scheduler::add_thread(const BAN::Function<void()>& function)
|
||||
{
|
||||
uintptr_t flags;
|
||||
asm volatile("pushf; pop %0" : "=r"(flags));
|
||||
asm volatile("cli");
|
||||
TRY(m_threads.emplace_back(function));
|
||||
if (flags & (1 << 9))
|
||||
asm volatile("sti");
|
||||
return {};
|
||||
}
|
||||
|
||||
void Scheduler::reschedule()
|
||||
{
|
||||
ASSERT(InterruptController::get().is_in_service(PIT_IRQ));
|
||||
@@ -62,9 +74,6 @@ namespace Kernel
|
||||
|
||||
Thread& current = *m_current_iterator;
|
||||
|
||||
//if (m_threads.size() == 2 && current.id() != 0 && current.state() == Thread::State::Running)
|
||||
// return;
|
||||
|
||||
if (current.state() == Thread::State::Done)
|
||||
{
|
||||
m_threads.remove(m_current_iterator);
|
||||
@@ -91,7 +100,7 @@ namespace Kernel
|
||||
{
|
||||
case Thread::State::NotStarted:
|
||||
next.set_state(Thread::State::Running);
|
||||
start_thread(next.args()[0], next.args()[1], next.args()[2], next.args()[3], next.rsp(), next.rip());
|
||||
start_thread(next.function(), next.rsp(), next.rip());
|
||||
break;
|
||||
case Thread::State::Paused:
|
||||
next.set_state(Thread::State::Running);
|
||||
@@ -123,8 +132,7 @@ namespace Kernel
|
||||
ASSERT(current.state() == Thread::State::NotStarted);
|
||||
current.set_state(Thread::State::Running);
|
||||
|
||||
const uintptr_t* args = current.args();
|
||||
start_thread(args[0], args[1], args[2], args[3], current.rsp(), current.rip());
|
||||
start_thread(current.function(), current.rsp(), current.rip());
|
||||
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
@@ -180,21 +180,18 @@ argument_done:
|
||||
{
|
||||
static SpinLock s_thread_spinlock;
|
||||
|
||||
// NOTE: This is a workaround to pass values as copies to threads.
|
||||
// I have only implemented passing integer and pointers.
|
||||
// We don't continue execution until the thread has unlocked
|
||||
// the spinlock.
|
||||
s_thread_spinlock.lock();
|
||||
MUST(Scheduler::get().add_thread(Function<void(const Vector<String>*)>(
|
||||
[this] (const Vector<String>* args_ptr)
|
||||
|
||||
MUST(Scheduler::get().add_thread(Function<void()>(
|
||||
[this, &arguments]
|
||||
{
|
||||
auto args = *args_ptr;
|
||||
s_thread_spinlock.unlock();
|
||||
auto args = arguments;
|
||||
args.remove(0);
|
||||
s_thread_spinlock.unlock();
|
||||
PIT::sleep(5000);
|
||||
process_command(args);
|
||||
}
|
||||
), &arguments));
|
||||
)));
|
||||
|
||||
while (s_thread_spinlock.is_locked());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
static uint32_t s_next_id = 0;
|
||||
static uint32_t s_next_tid = 0;
|
||||
|
||||
static constexpr size_t thread_stack_size = 16384;
|
||||
|
||||
@@ -21,26 +21,19 @@ namespace Kernel
|
||||
memcpy((void*)rsp, (void*)&value, size);
|
||||
}
|
||||
|
||||
Thread::Thread(uintptr_t rip, uintptr_t func, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3)
|
||||
: m_id(s_next_id++)
|
||||
Thread::Thread(const BAN::Function<void()>& function)
|
||||
: m_tid(s_next_tid++)
|
||||
, m_function(function)
|
||||
{
|
||||
m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE);
|
||||
ASSERT(m_stack_base);
|
||||
|
||||
m_rsp = (uintptr_t)m_stack_base + thread_stack_size;
|
||||
m_rip = rip;
|
||||
m_args[1] = arg1;
|
||||
m_args[2] = arg2;
|
||||
m_args[3] = arg3;
|
||||
|
||||
// NOTE: in System V ABI arg0 is the pointer to 'this'
|
||||
// we copy the function object to Thread object
|
||||
// so we can ensure the lifetime of it. We store
|
||||
// it as raw bytes so that Thread can be non-templated.
|
||||
// This requires BAN::Function to be trivially copyable
|
||||
// but for now it should be.
|
||||
memcpy(m_function, (void*)func, sizeof(m_function));
|
||||
m_args[0] = (uintptr_t)m_function;
|
||||
m_rsp = (uintptr_t)m_stack_base + thread_stack_size;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpmf-conversions"
|
||||
m_rip = (uintptr_t)(void*)&BAN::Function<void()>::operator();
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
write_to_stack<sizeof(void*)>(m_rsp, this);
|
||||
write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit);
|
||||
|
||||
Reference in New Issue
Block a user