diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 314d2df948..7b409876f3 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -2861,16 +2861,23 @@ int Process::thread_count() const return count; } -int Process::sys$create_thread(void* (*entry)(void*), void* argument) +int Process::sys$create_thread(void* (*entry)(void*), void* argument, void* stack) { if (!validate_read((const void*)entry, sizeof(void*))) return -EFAULT; + if (!MM.validate_user_stack(*this, VirtualAddress(((u32)stack) - 4))) + return -EFAULT; auto* thread = new Thread(*this); auto& tss = thread->tss(); tss.eip = (u32)entry; tss.eflags = 0x0202; tss.cr3 = page_directory().cr3(); - thread->make_userspace_stack_for_secondary_thread(argument); + tss.esp = (u32)stack; + + // NOTE: The stack needs to be 16-byte aligned. + thread->push_value_on_stack((u32)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 1e912aaa61..58a2d39887 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -204,7 +204,7 @@ public: 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$restore_signal_mask(u32 mask); - int sys$create_thread(void* (*)(void*), void*); + int sys$create_thread(void* (*)(void*), void* argument, void* stack); void sys$exit_thread(void*); int sys$join_thread(int tid, void** exit_value); int sys$rename(const char* oldpath, const char* newpath); diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index f1034e61e4..84bf19188a 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -601,18 +601,6 @@ void Thread::make_userspace_stack_for_main_thread(Vector arguments, Vect push_value_on_stack(0); } -void Thread::make_userspace_stack_for_secondary_thread(void* argument) -{ - m_userspace_stack_region = m_process.allocate_region(VirtualAddress(), default_userspace_stack_size, String::format("Stack (Thread %d)", tid()), PROT_READ | PROT_WRITE, false); - ASSERT(m_userspace_stack_region); - m_userspace_stack_region->set_stack(true); - m_tss.esp = m_userspace_stack_region->vaddr().offset(default_userspace_stack_size).get(); - - // NOTE: The stack needs to be 16-byte aligned. - push_value_on_stack((u32)argument); - push_value_on_stack(0); -} - Thread* Thread::clone(Process& process) { auto* clone = new Thread(process); diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 0fd9b9ad37..7017df3dd9 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -325,7 +325,6 @@ public: void set_default_signal_dispositions(); void push_value_on_stack(u32); void make_userspace_stack_for_main_thread(Vector arguments, Vector environment); - void make_userspace_stack_for_secondary_thread(void* argument); void make_thread_specific_region(Badge); diff --git a/Libraries/LibC/unistd.cpp b/Libraries/LibC/unistd.cpp index d0f6af955a..809d705187 100644 --- a/Libraries/LibC/unistd.cpp +++ b/Libraries/LibC/unistd.cpp @@ -509,18 +509,6 @@ char* getlogin() return nullptr; } -int create_thread(void* (*entry)(void*), void* argument) -{ - int rc = syscall(SC_create_thread, entry, argument); - __RETURN_WITH_ERRNO(rc, rc, -1); -} - -void exit_thread(void* code) -{ - syscall(SC_exit_thread, code); - ASSERT_NOT_REACHED(); -} - int ftruncate(int fd, off_t length) { int rc = syscall(SC_ftruncate, fd, length); diff --git a/Libraries/LibC/unistd.h b/Libraries/LibC/unistd.h index 8f57122693..c7999b335c 100644 --- a/Libraries/LibC/unistd.h +++ b/Libraries/LibC/unistd.h @@ -35,8 +35,6 @@ void sysbeep(); int systrace(pid_t); int gettid(); int donate(int tid); -int create_thread(void *(*)(void*), void* argument); -void exit_thread(void*); int create_shared_buffer(int, void** buffer); int share_buffer_with(int, pid_t peer_pid); int share_buffer_globally(int); diff --git a/Libraries/LibPthread/pthread.cpp b/Libraries/LibPthread/pthread.cpp index b1e17b1f61..ba844ce400 100644 --- a/Libraries/LibPthread/pthread.cpp +++ b/Libraries/LibPthread/pthread.cpp @@ -1,18 +1,36 @@ +#include #include #include #include #include -#include #include +#include +#include extern "C" { +static int create_thread(void* (*entry)(void*), void* argument, void* stack) +{ + int rc = syscall(SC_create_thread, entry, argument, stack); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + +static void exit_thread(void* code) +{ + syscall(SC_exit_thread, code); + ASSERT_NOT_REACHED(); +} + int pthread_create(pthread_t* thread, pthread_attr_t* attributes, void* (*start_routine)(void*), void* argument_to_start_routine) { if (!thread) return -EINVAL; UNUSED_PARAM(attributes); - int rc = create_thread(start_routine, argument_to_start_routine); + const size_t stack_size = 4 * MB; + auto* stack = (u8*)mmap_with_name(nullptr, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 0, 0, "Thread stack"); + if (!stack) + return -1; + int rc = create_thread(start_routine, argument_to_start_routine, stack + stack_size); if (rc < 0) return rc; *thread = rc; @@ -55,5 +73,4 @@ int pthread_mutex_unlock(pthread_mutex_t* mutex) atomic->store(false, AK::memory_order_release); return 0; } - }