Переглянути джерело

feat(syscall): impl. fork

greatbridf 2 роки тому
батько
коміт
ecd76edc09

+ 7 - 0
include/kernel/process.hpp

@@ -8,6 +8,8 @@
 #include <kernel/mm.hpp>
 #include <types/list.hpp>
 
+typedef size_t pid_t;
+
 class process;
 struct thread;
 
@@ -36,10 +38,12 @@ public:
     types::list<thread> thds;
     void* k_esp;
     process_attr attr;
+    pid_t pid;
 
 public:
     process(process&& val);
     process(const process&) = delete;
+    process(const process& proc, const thread& main_thread);
     process(void* start_eip, uint8_t* image, size_t image_size, bool system);
 };
 
@@ -55,6 +59,9 @@ void thread_context_load(interrupt_stack* int_stack, thread* thd, bool kernel);
 void process_context_save(interrupt_stack*, process*);
 void process_context_load(interrupt_stack*, process* proc);
 
+void add_to_process_list(process&& proc);
+void add_to_ready_list(thread* thd);
+
 #else
 
 void NORETURN init_scheduler();

+ 41 - 0
src/kernel/process.cpp

@@ -19,6 +19,7 @@ static inline void* align_down_to_16byte(void* addr)
 static bool is_scheduler_ready;
 static types::list<process>* processes;
 static types::list<thread*>* ready_thds;
+static pid_t max_pid = 1;
 
 thread* current_thread;
 process* current_process;
@@ -26,6 +27,7 @@ process* current_process;
 process::process(process&& val)
     : mms(types::move(val.mms))
     , thds(types::move(val.thds))
+    , pid(val.pid)
 {
     if (current_process == &val)
         current_process = this;
@@ -40,10 +42,39 @@ process::process(process&& val)
     val.attr.system = 0;
 }
 
+process::process(const process& val, const thread& main_thd)
+    : mms(*kernel_mms)
+    , attr { .system = val.attr.system }
+    , pid { max_pid++ }
+{
+    k_esp = align_down_to_16byte((char*)k_malloc(THREAD_KERNEL_STACK_SIZE) + THREAD_KERNEL_STACK_SIZE);
+    memset((char*)k_esp - THREAD_KERNEL_STACK_SIZE, 0x00, THREAD_KERNEL_STACK_SIZE);
+    auto iter_thd = thds.emplace_back(main_thd);
+    iter_thd->owner = this;
+
+    page_directory_entry* pd = alloc_pd();
+    memcpy(pd, mms_get_pd(kernel_mms), PAGE_SIZE);
+
+    mms.begin()->pd = pd;
+    // skip kernel heap
+    for (auto iter_src = ++val.mms.cbegin(); iter_src != val.mms.cend(); ++iter_src) {
+        auto iter_dst = mms.emplace_back(iter_src->start, pd, iter_src->attr.write, iter_src->attr.system);
+        iter_dst->pd = pd;
+        for (auto pg = iter_src->pgs->begin(); pg != iter_src->pgs->end(); ++pg)
+            k_map(iter_dst.ptr(),
+                    &*pg,
+                    iter_src->attr.read,
+                    iter_src->attr.write,
+                    iter_src->attr.system,
+                    1);
+    }
+}
+
 process::process(void* start_eip, uint8_t* image, size_t image_size, bool system)
     : mms(*kernel_mms)
     , thds {}
     , attr { .system = system }
+    , pid { max_pid++ }
 {
     k_esp = align_down_to_16byte((char*)k_malloc(THREAD_KERNEL_STACK_SIZE) + THREAD_KERNEL_STACK_SIZE);
     memset((char*)k_esp - THREAD_KERNEL_STACK_SIZE, 0x00, THREAD_KERNEL_STACK_SIZE);
@@ -150,6 +181,16 @@ void process_context_load(interrupt_stack*, process* proc)
     current_process = proc;
 }
 
+void add_to_process_list(process&& proc)
+{
+    processes->push_back(types::move(proc));
+}
+
+void add_to_ready_list(thread* thd)
+{
+    ready_thds->push_back(thd);
+}
+
 void do_scheduling(interrupt_stack* intrpt_data)
 {
     if (!is_scheduler_ready)

+ 20 - 2
src/kernel/syscall.cpp

@@ -13,13 +13,27 @@ void _syscall_not_impl(interrupt_stack* data)
 
 void _syscall_fork(interrupt_stack* data)
 {
-    data->s_regs.eax = 0xfafafafa;
-    data->s_regs.edx = 0xfefefefe;
+    thread_context_save(data, current_thread, current_process->attr.system);
+    process_context_save(data, current_process);
+
+    process new_proc(*current_process, *current_thread);
+    thread* new_thd = new_proc.thds.begin().ptr();
+
+    // return value
+    new_thd->regs.eax = 0;
+    data->s_regs.eax = new_proc.pid;
+
+    new_thd->regs.edx = 0;
+    data->s_regs.edx = 0;
+
+    add_to_process_list(types::move(new_proc));
+    add_to_ready_list(new_thd);
 }
 
 void _syscall_write(interrupt_stack* data)
 {
     tty_print(console, reinterpret_cast<const char*>(data->s_regs.edi));
+
     data->s_regs.eax = 0;
     data->s_regs.edx = 0;
 }
@@ -28,6 +42,10 @@ void _syscall_sleep(interrupt_stack* data)
 {
     current_thread->attr.ready = 0;
     current_thread->attr.wait = 1;
+
+    data->s_regs.eax = 0;
+    data->s_regs.edx = 0;
+
     do_scheduling(data);
 }
 

+ 8 - 0
user-space-program/interrupt-test.s

@@ -3,6 +3,14 @@
 
 .globl user_interrupt_test
 user_interrupt_test:
+# fork 1 -> 2
+	xorl %eax, %eax
+	int $0x80
+	movl %eax, %esi
+# fork 2 -> 4
+	xorl %eax, %eax
+	int $0x80
+	movl %eax, %ecx
 # write
 	movl $1, %eax
 	movl $__user_interrupt_test_string, %edi