diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index c761a9fcf6..c1c8483d0a 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -3754,7 +3754,7 @@ void Process::send_signal(u8 signal, Process* sender) thread->send_signal(signal, sender); } -int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Syscall::SC_create_thread_params* user_params) +int Process::sys$create_thread(void* (*entry)(void*), const Syscall::SC_create_thread_params* user_params) { REQUIRE_PROMISE(thread); if (!validate_read((const void*)entry, sizeof(void*))) @@ -3806,10 +3806,6 @@ int Process::sys$create_thread(void* (*entry)(void*), void* argument, const Sysc tss.cr3 = page_directory().cr3(); tss.esp = user_stack_address; - // NOTE: The stack needs to be 16-byte aligned. - thread->push_value_on_stack((FlatPtr)argument); - thread->push_value_on_stack(0); - thread->make_thread_specific_region({}); thread->set_state(Thread::State::Runnable); return thread->tid(); diff --git a/Kernel/Process.h b/Kernel/Process.h index bd90430c27..16c10d8705 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -272,7 +272,7 @@ public: int sys$getpeername(const Syscall::SC_getpeername_params*); int sys$sched_setparam(pid_t pid, const struct sched_param* param); int sys$sched_getparam(pid_t pid, struct sched_param* param); - int sys$create_thread(void* (*)(void*), void* argument, const Syscall::SC_create_thread_params*); + int sys$create_thread(void* (*)(void*), const Syscall::SC_create_thread_params*); void sys$exit_thread(void*); int sys$join_thread(int tid, void** exit_value); int sys$detach_thread(int tid); diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp index b4eb057249..8967a7f2e8 100644 --- a/Libraries/LibPthread/pthread.cpp +++ b/Libraries/LibPthread/pthread.cpp @@ -50,9 +50,37 @@ constexpr size_t highest_reasonable_stack_size = 8 * MB; // That's the default i extern "C" { -static int create_thread(void* (*entry)(void*), void* argument, void* thread_params) +static void* pthread_create_helper(void* (*routine)(void*), void* argument) { - return syscall(SC_create_thread, entry, argument, thread_params); + void* ret_val = routine(argument); + pthread_exit(ret_val); + return nullptr; +} + +static int create_thread(void* (*entry)(void*), void* argument, PthreadAttrImpl* thread_params) +{ + void** stack = (void**)((uintptr_t)thread_params->m_stack_location + thread_params->m_stack_size); + + auto push_on_stack = [&](void* data) { + stack--; + *stack = data; + thread_params->m_stack_size -= sizeof(void*); + }; + + // We set up the stack for pthread_create_helper. + // Note that we need to align the stack to 16B, accounting for + // the fact that we also push 8 bytes. + while (((uintptr_t)stack - 8) % 16 != 0) + push_on_stack(nullptr); + + push_on_stack(argument); + push_on_stack((void*)entry); + ASSERT((uintptr_t)stack % 16 == 0); + + // Push a fake return address + push_on_stack(nullptr); + + return syscall(SC_create_thread, pthread_create_helper, thread_params); } static void exit_thread(void* code)