From e561ab1b0b0c3e37d729ce6620f375ac8fefc0b6 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 23 Mar 2019 22:59:08 +0100 Subject: [PATCH] Kernel+LibC: Add a simple create_thread() syscall. It takes two parameters, a function pointer for the entry function, and a void* argument to be passed to that function on the new thread. --- Kernel/Process.cpp | 17 ++++++++++++++++- Kernel/Process.h | 1 + Kernel/Syscall.cpp | 2 ++ Kernel/Syscall.h | 1 + Kernel/Thread.cpp | 15 +++++++++++++-- Kernel/Thread.h | 3 ++- Kernel/i386.cpp | 3 ++- Kernel/sync.sh | 1 + LibC/unistd.cpp | 6 ++++++ LibC/unistd.h | 1 + 10 files changed, 45 insertions(+), 5 deletions(-) diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 4ac23417adc..6f771297d14 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -406,7 +406,7 @@ int Process::do_exec(String path, Vector arguments, Vector envir main_thread().m_tss.gs = 0x23; main_thread().m_tss.ss = 0x23; main_thread().m_tss.cr3 = page_directory().cr3(); - main_thread().make_userspace_stack(move(arguments), move(environment)); + main_thread().make_userspace_stack_for_main_thread(move(arguments), move(environment)); main_thread().m_tss.ss0 = 0x10; main_thread().m_tss.esp0 = old_esp0; main_thread().m_tss.ss2 = m_pid; @@ -2452,3 +2452,18 @@ int Process::thread_count() const }); return count; } + +int Process::sys$create_thread(int(*entry)(void*), void* argument) +{ + if (!validate_read((const void*)entry, sizeof(void*))) + return -EFAULT; + auto* thread = new Thread(*this); + auto& tss = thread->tss(); + tss.eip = (dword)entry; + tss.eflags = 0x0202; + tss.cr3 = page_directory().cr3(); + thread->make_userspace_stack_for_secondary_thread(argument); + + thread->set_state(Thread::State::Runnable); + return 0; +} diff --git a/Kernel/Process.h b/Kernel/Process.h index 20084c4e739..40a4c4234a2 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -178,6 +178,7 @@ public: int sys$getsockopt(const Syscall::SC_getsockopt_params*); int sys$setsockopt(const Syscall::SC_setsockopt_params*); int sys$restore_signal_mask(dword mask); + int sys$create_thread(int(*)(void*), void*); int sys$create_shared_buffer(pid_t peer_pid, int, void** buffer); void* sys$get_shared_buffer(int shared_buffer_id); diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index ffb59b53866..fcc5845787a 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -235,6 +235,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, return current->process().sys$getsockopt((const SC_getsockopt_params*)arg1); case Syscall::SC_setsockopt: return current->process().sys$setsockopt((const SC_setsockopt_params*)arg1); + case Syscall::SC_create_thread: + return current->process().sys$create_thread((int(*)(void*))arg1, (void*)arg2); default: kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3); break; diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 417ce12dd62..8124cbc6949 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -92,6 +92,7 @@ __ENUMERATE_SYSCALL(recvfrom) \ __ENUMERATE_SYSCALL(getsockopt) \ __ENUMERATE_SYSCALL(setsockopt) \ + __ENUMERATE_SYSCALL(create_thread) \ namespace Syscall { diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index c3e61bf0c96..cdc840ffff5 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -435,7 +435,7 @@ void Thread::push_value_on_stack(dword value) *stack_ptr = value; } -void Thread::make_userspace_stack(Vector arguments, Vector environment) +void Thread::make_userspace_stack_for_main_thread(Vector arguments, Vector environment) { auto* region = m_process.allocate_region(LinearAddress(), default_userspace_stack_size, "stack"); ASSERT(region); @@ -482,12 +482,23 @@ void Thread::make_userspace_stack(Vector arguments, Vector envir push_value_on_stack(0); } +void Thread::make_userspace_stack_for_secondary_thread(void *argument) +{ + auto* region = m_process.allocate_region(LinearAddress(), default_userspace_stack_size, String::format("Thread %u Stack", tid())); + ASSERT(region); + m_stack_top3 = region->laddr().offset(default_userspace_stack_size).get(); + m_tss.esp = m_stack_top3; + + // NOTE: The stack needs to be 16-byte aligned. + push_value_on_stack((dword)argument); + push_value_on_stack(0); +} + Thread* Thread::clone(Process& process) { auto* clone = new Thread(process); memcpy(clone->m_signal_action_data, m_signal_action_data, sizeof(m_signal_action_data)); clone->m_signal_mask = m_signal_mask; - //clone->m_tss = m_tss; clone->m_fpu_state = m_fpu_state; clone->m_has_used_fpu = m_has_used_fpu; return clone; diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 85be55caa7a..c4a0095eef8 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -116,7 +116,8 @@ public: void set_default_signal_dispositions(); void push_value_on_stack(dword); - void make_userspace_stack(Vector arguments, Vector environment); + void make_userspace_stack_for_main_thread(Vector arguments, Vector environment); + void make_userspace_stack_for_secondary_thread(void* argument); Thread* clone(Process&); diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 44103f0b82d..3133b9ae4ee 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -273,9 +273,10 @@ void exception_14_handler(RegisterDumpWithExceptionCode& regs) auto response = MM.handle_page_fault(PageFault(regs.exception_code, LinearAddress(faultAddress))); if (response == PageFaultResponse::ShouldCrash) { - kprintf("%s(%u) unrecoverable page fault, %s laddr=%p\n", + kprintf("%s(%u:%u) unrecoverable page fault, %s laddr=%p\n", current->process().name().characters(), current->pid(), + current->tid(), regs.exception_code & 2 ? "write" : "read", faultAddress); dump(regs); diff --git a/Kernel/sync.sh b/Kernel/sync.sh index 52e94cf3821..2cd35850087 100755 --- a/Kernel/sync.sh +++ b/Kernel/sync.sh @@ -89,6 +89,7 @@ cp -v ../Applications/About/About mnt/bin/About cp -v ../Applications/TextEditor/TextEditor mnt/bin/TextEditor cp -v ../Applications/IRCClient/IRCClient mnt/bin/IRCClient ln -s IRCClient mnt/bin/irc +ln -s FileManager mnt/bin/fm cp -v ../Servers/LookupServer/LookupServer mnt/bin/LookupServer cp -v ../Servers/WindowServer/WindowServer mnt/bin/WindowServer cp -v kernel.map mnt/ diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index de24904dd09..1ad4db0d6ec 100644 --- a/LibC/unistd.cpp +++ b/LibC/unistd.cpp @@ -410,4 +410,10 @@ char* getlogin() return nullptr; } +int create_thread(int(*entry)(void*), void* argument) +{ + int rc = syscall(SC_create_thread, entry, argument); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + } diff --git a/LibC/unistd.h b/LibC/unistd.h index 7d33acd22a1..27f0c73a88f 100644 --- a/LibC/unistd.h +++ b/LibC/unistd.h @@ -14,6 +14,7 @@ __BEGIN_DECLS extern char** environ; +int create_thread(int(*)(void*), void*); int create_shared_buffer(pid_t peer_pid, int, void** buffer); void* get_shared_buffer(int shared_buffer_id); int release_shared_buffer(int shared_buffer_id);