Browse Source

change(proclist): remove emplace from proclist;

the kernel thread daemon and init process creation are moved
into proclist::proclist()
greatbridf 11 months ago
parent
commit
1c7a276b93
3 changed files with 133 additions and 141 deletions
  1. 14 17
      include/kernel/process.hpp
  2. 97 111
      src/kernel/process.cpp
  3. 22 13
      src/kernel/syscall.cpp

+ 14 - 17
include/kernel/process.hpp

@@ -278,27 +278,18 @@ public:
     void send_signal(kernel::signal_list::signo_type signal);
 };
 
-namespace kernel::kinit {
-
-// in process.cpp
-void create_kthreadd_process();
-
-} // namespace kernel::kinit
-
 class proclist final {
 private:
     std::map<pid_t, process> m_procs;
-    pid_t m_nextpid = 1;
+    pid_t m_nextpid = 2;
 
     constexpr pid_t next_pid() { return m_nextpid++; }
     process& real_emplace(pid_t pid, pid_t ppid);
 
-    friend void kernel::kinit::create_kthreadd_process();
-
 public:
-    process& emplace(pid_t ppid);
+    proclist();
 
-    process& copy_from(process& proc)
+    constexpr process& copy_from(process& proc)
     {
         pid_t pid = next_pid();
         auto [ iter, inserted ] = m_procs.try_emplace(pid, proc, pid);
@@ -320,15 +311,21 @@ public:
         m_procs.erase(proc_iter);
     }
 
-    constexpr bool try_find(pid_t pid) const
-    { return m_procs.find(pid); }
+    constexpr std::pair<process*, bool> try_find(pid_t pid) const
+    {
+        auto iter = m_procs.find(pid);
+        if (iter)
+            return { (process*)&iter->second, true };
+        else
+            return { nullptr, false };
+    }
 
     // if process doesn't exist, the behavior is undefined
     constexpr process& find(pid_t pid)
     {
-        auto iter = m_procs.find(pid);
-        assert(iter);
-        return iter->second;
+        auto [ ptr, found] = try_find(pid);
+        assert(found);
+        return *ptr;
     }
 
     constexpr void make_children_orphans(pid_t pid)

+ 97 - 111
src/kernel/process.cpp

@@ -213,7 +213,12 @@ process::process(const process& parent, pid_t pid)
 
 process::process(pid_t pid, pid_t ppid)
     : attr { .system = true }
-    , pwd { "/" } , pid { pid } , ppid { ppid } { }
+    , pwd { "/" } , pid { pid } , ppid { ppid }
+{
+    bool inserted;
+    std::tie(std::ignore, inserted) = thds.emplace("", pid);
+    assert(inserted);
+}
 
 using kernel::tasks::thread;
 using signo_type = kernel::signal_list::signo_type;
@@ -326,24 +331,103 @@ int thread::load_thread_area() const
     return 0;
 }
 
-process& proclist::real_emplace(pid_t pid, pid_t ppid)
+void kernel_threadd_main(void)
 {
-    auto [ iter, inserted ] = m_procs.try_emplace(pid, pid, ppid);
-    assert(inserted);
+    kmsg("kernel thread daemon started\n");
 
-    if (ppid && try_find(ppid)) {
-        bool success = false;
-        std::tie(std::ignore, success) =
-            find(ppid).children.insert(pid);
-        assert(success);
+    for (;;) {
+        if (kthreadd_new_thd_func) {
+            void (*func)(void*) = nullptr;
+            void* data = nullptr;
+
+            if (1) {
+                types::lock_guard lck(kthreadd_mtx);
+
+                if (kthreadd_new_thd_func) {
+                    func = std::exchange(kthreadd_new_thd_func, nullptr);
+                    data = std::exchange(kthreadd_new_thd_data, nullptr);
+                }
+            }
+
+            // TODO
+            (void)func, (void)data;
+            assert(false);
+
+            // syscall_fork
+            // int ret = syscall(0x00);
+
+            // if (ret == 0) {
+            //     // child process
+            //     func(data);
+            //     // the function shouldn't return here
+            //     assert(false);
+            // }
+        }
+        // TODO: sleep here to wait for new_kernel_thread event
+        asm_hlt();
     }
+}
 
-    return iter->second;
+SECTION(".text.kinit")
+proclist::proclist()
+{
+    // init process has no parent
+    auto& init = real_emplace(1, 0);
+    assert(init.pid == 1 && init.ppid == 0);
+
+    auto& thd = *init.thds.begin();
+    thd.name.assign("[kernel init]");
+
+    init.files.open(init, "/dev/console", O_RDONLY, 0);
+    init.files.open(init, "/dev/console", O_WRONLY, 0);
+    init.files.open(init, "/dev/console", O_WRONLY, 0);
+
+    current_process = &init;
+    current_thread = &thd;
+    readythds->push(current_thread);
+
+    tss.ss0 = KERNEL_DATA_SEGMENT;
+    tss.esp0 = (uint32_t)current_thread->kstack.esp;
+
+    current_process->mms.switch_pd();
+
+    if (1) {
+        // pid 0 is kernel thread daemon
+        auto& proc = real_emplace(0, 0);
+        assert(proc.pid == 0 && proc.ppid == 0);
+
+        // create thread
+        auto& thd = *proc.thds.begin();
+        thd.name.assign("[kernel thread daemon]");
+
+        auto* esp = &thd.kstack.esp;
+        auto old_esp = (uint32_t)thd.kstack.esp;
+
+        // return(start) address
+        push_stack(esp, (uint32_t)kernel_threadd_main);
+        // ebx
+        push_stack(esp, 0);
+        // edi
+        push_stack(esp, 0);
+        // esi
+        push_stack(esp, 0);
+        // ebp
+        push_stack(esp, 0);
+        // eflags
+        push_stack(esp, 0x200);
+        // original esp
+        push_stack(esp, old_esp);
+
+        readythds->push(&thd);
+    }
 }
 
-process& proclist::emplace(pid_t ppid)
+process& proclist::real_emplace(pid_t pid, pid_t ppid)
 {
-    return real_emplace(next_pid(), ppid);
+    auto [ iter, inserted ] = m_procs.try_emplace(pid, pid, ppid);
+    assert(inserted);
+
+    return iter->second;
 }
 
 void proclist::kill(pid_t pid, int exit_code)
@@ -410,43 +494,6 @@ void proclist::kill(pid_t pid, int exit_code)
     parent.cv_wait.notify();
 }
 
-void kernel_threadd_main(void)
-{
-    kmsg("kernel thread daemon started\n");
-
-    for (;;) {
-        if (kthreadd_new_thd_func) {
-            void (*func)(void*) = nullptr;
-            void* data = nullptr;
-
-            if (1) {
-                types::lock_guard lck(kthreadd_mtx);
-
-                if (kthreadd_new_thd_func) {
-                    func = std::exchange(kthreadd_new_thd_func, nullptr);
-                    data = std::exchange(kthreadd_new_thd_data, nullptr);
-                }
-            }
-
-            // TODO
-            (void)func, (void)data;
-            assert(false);
-
-            // syscall_fork
-            // int ret = syscall(0x00);
-
-            // if (ret == 0) {
-            //     // child process
-            //     func(data);
-            //     // the function shouldn't return here
-            //     assert(false);
-            // }
-        }
-        // TODO: sleep here to wait for new_kernel_thread event
-        asm_hlt();
-    }
-}
-
 static void release_kinit()
 {
     extern char __stage1_start[];
@@ -467,48 +514,8 @@ static void release_kinit()
     }
 }
 
-namespace kernel::kinit {
-
-SECTION(".text.kinit")
-void create_kthreadd_process()
-{
-    // pid 2 is kernel thread daemon
-    auto& proc = procs->real_emplace(0, 0);
-    assert(proc.pid == 0);
-
-    // create thread
-    auto [ iter_thd, inserted] =
-        proc.thds.emplace("[kernel thread daemon]", proc.pid);
-    assert(inserted);
-    auto& thd = *iter_thd;
-
-    auto* esp = &thd.kstack.esp;
-    auto old_esp = (uint32_t)thd.kstack.esp;
-
-    // return(start) address
-    push_stack(esp, (uint32_t)kernel_threadd_main);
-    // ebx
-    push_stack(esp, 0);
-    // edi
-    push_stack(esp, 0);
-    // esi
-    push_stack(esp, 0);
-    // ebp
-    push_stack(esp, 0);
-    // eflags
-    push_stack(esp, 0x200);
-    // original esp
-    push_stack(esp, old_esp);
-
-    readythds->push(&thd);
-}
-
-} // namespace kernel::kinit
-
 void NORETURN _kernel_init(void)
 {
-    kernel::kinit::create_kthreadd_process();
-
     release_kinit();
 
     asm_sti();
@@ -593,29 +600,8 @@ void k_new_thread(void (*func)(void*), void* data)
 SECTION(".text.kinit")
 void NORETURN init_scheduler(void)
 {
-    procs = new proclist;
     readythds = new readyqueue;
-
-    // init process has no parent
-    auto& init = procs->emplace(0);
-    assert(init.pid == 1);
-
-    auto [ iter_thd, inserted ] = init.thds.emplace("[kernel init]", init.pid);
-    assert(inserted);
-    auto& thd = *iter_thd;
-
-    init.files.open(init, "/dev/console", O_RDONLY, 0);
-    init.files.open(init, "/dev/console", O_WRONLY, 0);
-    init.files.open(init, "/dev/console", O_WRONLY, 0);
-
-    current_process = &init;
-    current_thread = &thd;
-    readythds->push(current_thread);
-
-    tss.ss0 = KERNEL_DATA_SEGMENT;
-    tss.esp0 = (uint32_t)current_thread->kstack.esp;
-
-    current_process->mms.switch_pd();
+    procs = new proclist;
 
     asm volatile(
         "movl %0, %%esp\n"

+ 22 - 13
src/kernel/syscall.cpp

@@ -325,13 +325,13 @@ int _syscall_getsid(interrupt_stack* data)
 {
     SYSCALL_ARG1(pid_t, pid);
 
-    if (!procs->try_find(pid))
+    auto [ pproc, found ] = procs->try_find(pid);
+    if (!found)
         return -ESRCH;
-    auto& proc = procs->find(pid);
-    if (proc.sid != current_process->sid)
+    if (pproc->sid != current_process->sid)
         return -EPERM;
 
-    return proc.sid;
+    return pproc->sid;
 }
 
 int _syscall_close(interrupt_stack* data)
@@ -374,15 +374,14 @@ int _syscall_setpgid(interrupt_stack* data)
     if (pgid == 0)
         pgid = pid;
 
-    if (!procs->try_find(pid))
+    auto [ pproc, found ] = procs->try_find(pid);
+    if (!found)
         return -ESRCH;
 
-    auto& proc = procs->find(pid);
-
     // TODO: check whether pgid and the original
     //       pgid is in the same session
 
-    proc.pgid = pgid;
+    pproc->pgid = pgid;
 
     return 0;
 }
@@ -461,7 +460,7 @@ int _syscall_set_tid_address(interrupt_stack* data)
 }
 
 // TODO: this operation SHOULD be atomic
-ssize_t _syscall_writev(interrupt_stack* data)
+int _syscall_writev(interrupt_stack* data)
 {
     SYSCALL_ARG1(int, fd);
     SYSCALL_ARG2(const iovec* __user, iov);
@@ -643,6 +642,14 @@ int _syscall_sendfile64(interrupt_stack* data)
         if (ret < 0)
             return ret;
         totn += ret;
+
+        // TODO: this won't work, since when we are in the syscall handler,
+        //       interrupts are blocked.
+        //       one solution is to put the sendfile action into a kernel
+        //       worker and pause the calling thread so that the worker
+        //       thread could be interrupted normally.
+        if (current_thread->signals.pending_signal() != 0)
+            return (totn == 0) ? -EINTR : totn;
     }
 
     return totn;
@@ -778,13 +785,14 @@ int _syscall_kill(interrupt_stack* data)
     SYSCALL_ARG1(pid_t, pid);
     SYSCALL_ARG2(int, sig);
 
-    if (!procs->try_find(pid))
+    auto [ pproc, found ] = procs->try_find(pid);
+    if (!found)
         return -ESRCH;
 
     if (!kernel::signal_list::check_valid(sig))
         return -EINVAL;
 
-    if (procs->find(pid).is_system())
+    if (pproc->is_system())
         return 0;
 
     // TODO: check permission
@@ -879,10 +887,11 @@ pid_t _syscall_getpgid(interrupt_stack* data)
     if (pid == 0)
         return current_process->pgid;
 
-    if (!procs->try_find(pid))
+    auto [ pproc, found ] = procs->try_find(pid);
+    if (!found)
         return -ESRCH;
 
-    return procs->find(pid).pgid;
+    return pproc->pgid;
 }
 
 int _syscall_gettid(interrupt_stack* data)