diff --git a/kernel/arch/i386/Thread.S b/kernel/arch/i386/Thread.S index 54e48a6552..af2cb91c22 100644 --- a/kernel/arch/i386/Thread.S +++ b/kernel/arch/i386/Thread.S @@ -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 diff --git a/kernel/arch/x86_64/Thread.S b/kernel/arch/x86_64/Thread.S index 8d3169269e..3c72cb179d 100644 --- a/kernel/arch/x86_64/Thread.S +++ b/kernel/arch/x86_64/Thread.S @@ -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 diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index c720e85d64..dd4399bcfb 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -9,7 +9,10 @@ namespace Kernel class Thread : public BAN::RefCounted { public: - static BAN::ErrorOr> create(const BAN::Function&); + using entry_t = void(*)(void*); + + public: + static BAN::ErrorOr> 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* function() const { return &m_function; } - private: - Thread(const BAN::Function&); + Thread(); + BAN::ErrorOr 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 m_function; friend class BAN::RefPtr; }; diff --git a/kernel/kernel/Scheduler.cpp b/kernel/kernel/Scheduler.cpp index c702cec3cf..df9fd4c3a5 100644 --- a/kernel/kernel/Scheduler.cpp +++ b/kernel/kernel/Scheduler.cpp @@ -15,7 +15,7 @@ namespace Kernel { - extern "C" void start_thread(const BAN::Function* 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(); diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 842b168c92..a7ad7d0a2b 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -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& 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") { diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index 3b1d8d0d1f..55a73c0031 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -21,33 +21,34 @@ namespace Kernel memcpy((void*)rsp, (void*)&value, size); } - - BAN::ErrorOr> Thread::create(const BAN::Function& function) + BAN::ErrorOr> Thread::create(entry_t entry, void* data) { - return BAN::RefPtr::create(function); + auto thread = TRY(BAN::RefPtr::create()); + TRY(thread->initialize(entry, data)); + return thread; } - Thread::Thread(const BAN::Function& function) + Thread::Thread() : m_tid(s_next_tid++) - , m_function(function) + {} + + BAN::ErrorOr 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::operator(); -#pragma GCC diagnostic pop + m_rip = (uintptr_t)entry; write_to_stack(m_rsp, this); write_to_stack(m_rsp, &Thread::on_exit); + write_to_stack(m_rsp, data); + + return {}; } Thread::~Thread() { - dprintln("thread {} destruct", tid()); kfree(m_stack_base); } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 9011fb24d4..54306332a6 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -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);