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)
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
start_thread:
movl 4(%esp), %eax
movl 12(%esp), %ecx
movl 8(%esp), %esp
pushl %eax
pushl $exit_thread_trampoline
movl 8(%esp), %ecx
movl 4(%esp), %esp
movl $0, %ebp
pushl $exit_thread_trampoline
sti
jmp *%ecx

View File

@ -8,14 +8,15 @@ exit_thread_trampoline:
movq 8(%rsp), %rdi
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
start_thread:
movq %rsi, %rsp
movq %rdi, %rsp
popq %rdi
movq $0, %rbp
pushq $exit_thread_trampoline
sti
jmp *%rdx
jmp *%rsi
# void continue_thread(uint64_t rsp, uint64_t rip)
.global continue_thread

View File

@ -9,7 +9,10 @@ namespace Kernel
class Thread : public BAN::RefCounted<Thread>
{
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();
uint32_t tid() const { return m_tid; }
@ -22,10 +25,9 @@ namespace Kernel
void set_started() { m_started = true; }
bool started() const { return m_started; }
const BAN::Function<void()>* function() const { return &m_function; }
private:
Thread(const BAN::Function<void()>&);
Thread();
BAN::ErrorOr<void> initialize(entry_t, void*);
void on_exit();
private:
@ -34,8 +36,6 @@ namespace Kernel
uintptr_t m_rsp = 0;
const uint32_t m_tid = 0;
bool m_started = false;
BAN::Function<void()> m_function;
friend class BAN::RefPtr<Thread>;
};

View File

@ -15,7 +15,7 @@
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" uintptr_t read_rip();
@ -26,7 +26,7 @@ namespace Kernel
ASSERT(s_instance == nullptr);
s_instance = new Scheduler();
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 {};
}
@ -159,7 +159,7 @@ namespace Kernel
else
{
current.set_started();
start_thread(current.function(), current.rsp(), current.rip());
start_thread(current.rsp(), current.rip());
}
ASSERT_NOT_REACHED();

View File

@ -178,24 +178,32 @@ argument_done:
}
else if (arguments.front() == "thread")
{
static SpinLock s_thread_spinlock;
struct thread_data_t
{
Shell* shell;
SpinLock& lock;
const Vector<String>& arguments;
};
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();
s_thread_spinlock.lock();
args.remove(0);
PIT::sleep(5000);
auto thread = TRY(Thread::create(
[this, &arguments]
{
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));
if (auto res = shell->process_command(args); res.is_error())
Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error());
};
while (s_thread_spinlock.is_locked());
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")
{

View File

@ -21,33 +21,34 @@ namespace Kernel
memcpy((void*)rsp, (void*)&value, size);
}
BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(const BAN::Function<void()>& function)
BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(entry_t entry, void* data)
{
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_function(function)
{}
BAN::ErrorOr<void> Thread::initialize(entry_t entry, void* data)
{
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;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpmf-conversions"
m_rip = (uintptr_t)(void*)&BAN::Function<void()>::operator();
#pragma GCC diagnostic pop
m_rip = (uintptr_t)entry;
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, data);
return {};
}
Thread::~Thread()
{
dprintln("thread {} destruct", tid());
kfree(m_stack_base);
}

View File

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