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)
|
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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
@ -34,8 +36,6 @@ namespace Kernel
|
||||||
uintptr_t m_rsp = 0;
|
uintptr_t m_rsp = 0;
|
||||||
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>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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(
|
if (auto res = shell->process_command(args); res.is_error())
|
||||||
[this, &arguments]
|
Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error());
|
||||||
{
|
};
|
||||||
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());
|
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")
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue