Ver código fonte

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.
Andreas Kling 6 anos atrás
pai
commit
e561ab1b0b
10 arquivos alterados com 45 adições e 5 exclusões
  1. 16 1
      Kernel/Process.cpp
  2. 1 0
      Kernel/Process.h
  3. 2 0
      Kernel/Syscall.cpp
  4. 1 0
      Kernel/Syscall.h
  5. 13 2
      Kernel/Thread.cpp
  6. 2 1
      Kernel/Thread.h
  7. 2 1
      Kernel/i386.cpp
  8. 1 0
      Kernel/sync.sh
  9. 6 0
      LibC/unistd.cpp
  10. 1 0
      LibC/unistd.h

+ 16 - 1
Kernel/Process.cpp

@@ -406,7 +406,7 @@ int Process::do_exec(String path, Vector<String> arguments, Vector<String> 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;
+}

+ 1 - 0
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);

+ 2 - 0
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;

+ 1 - 0
Kernel/Syscall.h

@@ -92,6 +92,7 @@
     __ENUMERATE_SYSCALL(recvfrom) \
     __ENUMERATE_SYSCALL(getsockopt) \
     __ENUMERATE_SYSCALL(setsockopt) \
+    __ENUMERATE_SYSCALL(create_thread) \
 
 
 namespace Syscall {

+ 13 - 2
Kernel/Thread.cpp

@@ -435,7 +435,7 @@ void Thread::push_value_on_stack(dword value)
     *stack_ptr = value;
 }
 
-void Thread::make_userspace_stack(Vector<String> arguments, Vector<String> environment)
+void Thread::make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> 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<String> arguments, Vector<String> 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;

+ 2 - 1
Kernel/Thread.h

@@ -116,7 +116,8 @@ public:
 
     void set_default_signal_dispositions();
     void push_value_on_stack(dword);
-    void make_userspace_stack(Vector<String> arguments, Vector<String> environment);
+    void make_userspace_stack_for_main_thread(Vector<String> arguments, Vector<String> environment);
+    void make_userspace_stack_for_secondary_thread(void* argument);
 
     Thread* clone(Process&);
 

+ 2 - 1
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);

+ 1 - 0
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/

+ 6 - 0
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);
+}
+
 }

+ 1 - 0
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);