forked from Bananymous/banan-os
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:
parent
8dbece9119
commit
af854ec9e1
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue