Kernel: Thread creation now takes void(*)() as entry and void* as data

This simplifies threading for the future and gets rid of (undefined?)
cast of member function pointer to address
This commit is contained in:
Bananymous 2023-03-09 15:25:39 +02:00
parent 8dbece9119
commit af854ec9e1
7 changed files with 60 additions and 55 deletions

View File

@ -9,18 +9,13 @@ exit_thread_trampoline:
pushl (%esp) pushl (%esp)
ret ret
# void start_thread(uint32_t function, uint32_t esp, uint32_t eip) # void start_thread(uint32_t esp, uint32_t eip)
.global start_thread .global start_thread
start_thread: start_thread:
movl 4(%esp), %eax movl 8(%esp), %ecx
movl 12(%esp), %ecx movl 4(%esp), %esp
movl 8(%esp), %esp
pushl %eax
pushl $exit_thread_trampoline
movl $0, %ebp movl $0, %ebp
pushl $exit_thread_trampoline
sti sti
jmp *%ecx jmp *%ecx

View File

@ -8,14 +8,15 @@ exit_thread_trampoline:
movq 8(%rsp), %rdi movq 8(%rsp), %rdi
ret ret
# void start_thread(uint64_t function, uint64_t rsp, uint64_t rip) # void start_thread(uint64_t rsp, uint64_t rip)
.global start_thread .global start_thread
start_thread: start_thread:
movq %rsi, %rsp movq %rdi, %rsp
popq %rdi
movq $0, %rbp movq $0, %rbp
pushq $exit_thread_trampoline pushq $exit_thread_trampoline
sti sti
jmp *%rdx jmp *%rsi
# void continue_thread(uint64_t rsp, uint64_t rip) # void continue_thread(uint64_t rsp, uint64_t rip)
.global continue_thread .global continue_thread

View File

@ -9,7 +9,10 @@ namespace Kernel
class Thread : public BAN::RefCounted<Thread> class Thread : public BAN::RefCounted<Thread>
{ {
public: public:
static BAN::ErrorOr<BAN::RefPtr<Thread>> create(const BAN::Function<void()>&); using entry_t = void(*)(void*);
public:
static BAN::ErrorOr<BAN::RefPtr<Thread>> create(entry_t, void* = nullptr);
~Thread(); ~Thread();
uint32_t tid() const { return m_tid; } uint32_t tid() const { return m_tid; }
@ -22,10 +25,9 @@ namespace Kernel
void set_started() { m_started = true; } void set_started() { m_started = true; }
bool started() const { return m_started; } bool started() const { return m_started; }
const BAN::Function<void()>* function() const { return &m_function; }
private: private:
Thread(const BAN::Function<void()>&); Thread();
BAN::ErrorOr<void> initialize(entry_t, void*);
void on_exit(); void on_exit();
private: private:
@ -35,8 +37,6 @@ namespace Kernel
const uint32_t m_tid = 0; const uint32_t m_tid = 0;
bool m_started = false; bool m_started = false;
BAN::Function<void()> m_function;
friend class BAN::RefPtr<Thread>; friend class BAN::RefPtr<Thread>;
}; };

View File

@ -15,7 +15,7 @@
namespace Kernel namespace Kernel
{ {
extern "C" void start_thread(const BAN::Function<void()>* function, uintptr_t rsp, uintptr_t rip); extern "C" void start_thread(uintptr_t rsp, uintptr_t rip);
extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip); extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip);
extern "C" uintptr_t read_rip(); extern "C" uintptr_t read_rip();
@ -26,7 +26,7 @@ namespace Kernel
ASSERT(s_instance == nullptr); ASSERT(s_instance == nullptr);
s_instance = new Scheduler(); s_instance = new Scheduler();
ASSERT(s_instance); ASSERT(s_instance);
s_instance->m_idle_thread = TRY(Thread::create([] { for (;;) asm volatile("hlt"); })); s_instance->m_idle_thread = TRY(Thread::create([](void*) { for (;;) asm volatile("hlt"); }));
return {}; return {};
} }
@ -159,7 +159,7 @@ namespace Kernel
else else
{ {
current.set_started(); current.set_started();
start_thread(current.function(), current.rsp(), current.rip()); start_thread(current.rsp(), current.rip());
} }
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();

View File

@ -178,24 +178,32 @@ argument_done:
} }
else if (arguments.front() == "thread") else if (arguments.front() == "thread")
{ {
static SpinLock s_thread_spinlock; struct thread_data_t
{
Shell* shell;
SpinLock& lock;
const Vector<String>& arguments;
};
s_thread_spinlock.lock(); auto function = [](void* data)
{
thread_data_t* thread_data = (thread_data_t*)data;
Shell* shell = thread_data->shell;
auto args = thread_data->arguments;
thread_data->lock.unlock();
auto thread = TRY(Thread::create( args.remove(0);
[this, &arguments] PIT::sleep(5000);
{
auto args = arguments;
args.remove(0);
s_thread_spinlock.unlock();
PIT::sleep(5000);
if (auto res = process_command(args); res.is_error())
TTY_PRINTLN("{}", res.error());
}
));
TRY(Scheduler::get().add_thread(thread));
while (s_thread_spinlock.is_locked()); if (auto res = shell->process_command(args); res.is_error())
Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error());
};
SpinLock spinlock;
thread_data_t thread_data = { this, spinlock, arguments };
spinlock.lock();
TRY(Scheduler::get().add_thread(TRY(Thread::create(function, &thread_data))));
while (spinlock.is_locked());
} }
else if (arguments.front() == "memory") else if (arguments.front() == "memory")
{ {

View File

@ -21,33 +21,34 @@ namespace Kernel
memcpy((void*)rsp, (void*)&value, size); memcpy((void*)rsp, (void*)&value, size);
} }
BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(entry_t entry, void* data)
BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(const BAN::Function<void()>& function)
{ {
return BAN::RefPtr<Thread>::create(function); auto thread = TRY(BAN::RefPtr<Thread>::create());
TRY(thread->initialize(entry, data));
return thread;
} }
Thread::Thread(const BAN::Function<void()>& function) Thread::Thread()
: m_tid(s_next_tid++) : m_tid(s_next_tid++)
, m_function(function) {}
BAN::ErrorOr<void> Thread::initialize(entry_t entry, void* data)
{ {
m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE); m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE);
ASSERT(m_stack_base); if (m_stack_base == nullptr)
return BAN::Error::from_errno(ENOMEM);
m_rsp = (uintptr_t)m_stack_base + thread_stack_size; m_rsp = (uintptr_t)m_stack_base + thread_stack_size;
m_rip = (uintptr_t)entry;
#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, this);
write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit); write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit);
write_to_stack<sizeof(void*)>(m_rsp, data);
return {};
} }
Thread::~Thread() Thread::~Thread()
{ {
dprintln("thread {} destruct", tid());
kfree(m_stack_base); kfree(m_stack_base);
} }

View File

@ -125,7 +125,7 @@ extern "C" void kernel_main()
MUST(Scheduler::initialize()); MUST(Scheduler::initialize());
Scheduler& scheduler = Scheduler::get(); Scheduler& scheduler = Scheduler::get();
MUST(scheduler.add_thread(MUST(Thread::create( MUST(scheduler.add_thread(MUST(Thread::create(
[terminal_driver] [](void* terminal_driver)
{ {
MUST(VirtualFileSystem::initialize()); MUST(VirtualFileSystem::initialize());
@ -133,16 +133,16 @@ extern "C" void kernel_main()
if (font_or_error.is_error()) if (font_or_error.is_error())
dprintln("{}", font_or_error.error()); dprintln("{}", font_or_error.error());
else else
terminal_driver->set_font(font_or_error.release_value()); ((TerminalDriver*)terminal_driver)->set_font(font_or_error.release_value());
} }, terminal_driver
)))); ))));
MUST(scheduler.add_thread(MUST(Thread::create( MUST(scheduler.add_thread(MUST(Thread::create(
[tty1] [](void* tty)
{ {
Shell* shell = new Shell(tty1); Shell* shell = new Shell((TTY*)tty);
ASSERT(shell); ASSERT(shell);
shell->run(); shell->run();
} }, tty1
)))); ))));
scheduler.start(); scheduler.start();
ASSERT(false); ASSERT(false);