Преглед на файлове

feat(kernel_thread): impl. kernel_thread forking

greatbridf преди 2 години
родител
ревизия
88add58cf5
променени са 4 файла, в които са добавени 96 реда и са изтрити 22 реда
  1. 4 0
      include/kernel/mm.hpp
  2. 4 4
      src/kernel/interrupt.cpp
  3. 24 4
      src/kernel/mem.cpp
  4. 64 14
      src/kernel/process.cpp

+ 4 - 0
include/kernel/mm.hpp

@@ -143,6 +143,10 @@ int k_map(
 // allocate a raw page
 page_t alloc_raw_page(void);
 
+// allocate n raw page(s)
+// @return the id of the first page allocated
+page_t alloc_n_raw_pages(size_t n);
+
 // allocate a struct page together with the raw page
 struct page allocate_page(void);
 

+ 4 - 4
src/kernel/interrupt.cpp

@@ -82,9 +82,9 @@ void init_pic(void)
 
 extern "C" void int6_handler(
     struct regs_32 s_regs,
-    uint32_t error_code,
     ptr_t eip,
-    uint16_t cs)
+    uint16_t cs,
+    uint32_t eflags)
 {
     char buf[512];
 
@@ -94,11 +94,11 @@ extern "C" void int6_handler(
         buf, 512,
         "eax: %x, ebx: %x, ecx: %x, edx: %x\n"
         "esp: %x, ebp: %x, esi: %x, edi: %x\n"
-        "eip: %x, cs: %x, error_code: %x   \n",
+        "eip: %x, cs: %x, eflags: %x       \n",
         s_regs.eax, s_regs.ebx, s_regs.ecx,
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
-        cs, error_code);
+        cs, eflags);
     tty_print(console, buf);
 
     tty_print(console, "----   HALTING SYSTEM   ----\n");

+ 24 - 4
src/kernel/mem.cpp

@@ -296,10 +296,30 @@ static inline void free_addr_range(phys_ptr_t start, phys_ptr_t end)
 
 page_t alloc_raw_page(void)
 {
-    for (page_t i = 0; i < 1024 * 1024; ++i) {
-        if (bm_test(mem_bitmap, i) == 0) {
-            mark_page(i);
-            return i;
+    return alloc_n_raw_pages(1);
+}
+
+// @return the max count (but less than n) of the pages continuously available
+static inline size_t _test_n_raw_pages(page_t start, size_t n)
+{
+    // *start is already allocated
+    if (bm_test(mem_bitmap, start))
+        return 0;
+
+    return 1 + ((n > 1) ? _test_n_raw_pages(start + 1, n - 1) : 0);
+}
+
+page_t alloc_n_raw_pages(size_t n)
+{
+    page_t first = 0;
+    while (first <= 1024 * 1024 - n) {
+        size_t max = _test_n_raw_pages(first, n);
+        if (max != n) {
+            first += (max + 1);
+        } else {
+            for (page_t i = first; i < first + n; ++i)
+                bm_set(mem_bitmap, i);
+            return first;
         }
     }
     MAKE_BREAK_POINT();

+ 64 - 14
src/kernel/process.cpp

@@ -6,6 +6,7 @@
 #include <kernel/tty.h>
 #include <kernel_main.h>
 #include <types/types.h>
+#include <types/lock.h>
 #include <hello-world.res>
 #include <interrupt-test.res>
 
@@ -13,15 +14,13 @@ extern "C" void NORETURN go_user_space(void* eip);
 extern "C" void NORETURN to_kernel(interrupt_stack* ret_stack);
 extern "C" void NORETURN to_user(interrupt_stack* ret_stack);
 
-static inline void* align_down_to_16byte(void* addr)
-{
-    return (void*)((uint32_t)addr & 0xfffffff0);
-}
-
 static bool is_scheduler_ready;
 static types::list<process>* processes;
 static types::list<thread*>* ready_thds;
 static pid_t max_pid = 1;
+void (* volatile kthreadd_new_thd_func)(void*);
+void  * volatile kthreadd_new_thd_data;
+uint32_t kthreadd_lock = 0;
 
 thread* current_thread;
 process* current_process;
@@ -49,13 +48,15 @@ process::process(const process& val, const thread& main_thd)
     , attr { .system = val.attr.system }
     , pid { max_pid++ }
 {
-    k_esp = (char*)k_malloc(THREAD_KERNEL_STACK_SIZE);
-    memset((char*)k_esp, 0x00, THREAD_KERNEL_STACK_SIZE);
-    k_esp = align_down_to_16byte((char*)k_esp + THREAD_KERNEL_STACK_SIZE);
     auto iter_thd = thds.emplace_back(main_thd);
     iter_thd->owner = this;
 
     if (!val.attr.system) {
+        // TODO: allocate low mem
+        k_esp = (void*)page_to_phys_addr(alloc_n_raw_pages(2));
+        memset((char*)k_esp, 0x00, THREAD_KERNEL_STACK_SIZE);
+        k_esp = (char*)k_esp + THREAD_KERNEL_STACK_SIZE;
+
         page_directory_entry* pd = alloc_pd();
         memcpy(pd, mms_get_pd(kernel_mms), PAGE_SIZE);
 
@@ -72,6 +73,19 @@ process::process(const process& val, const thread& main_thd)
                         iter_src->attr.system,
                         1);
         }
+    } else {
+        // TODO: allocate low mem
+        k_esp = (void*)page_to_phys_addr(alloc_n_raw_pages(2));
+        memcpy(k_esp, main_thd.owner->k_esp, THREAD_KERNEL_STACK_SIZE);
+        k_esp = (char*)k_esp + THREAD_KERNEL_STACK_SIZE;
+
+        auto orig_k_esp = (uint32_t)main_thd.owner->k_esp;
+
+        iter_thd->regs.ebp -= orig_k_esp;
+        iter_thd->regs.ebp += (uint32_t)k_esp;
+
+        iter_thd->regs.esp -= orig_k_esp;
+        iter_thd->regs.esp += (uint32_t)k_esp;
     }
 }
 
@@ -81,9 +95,10 @@ process::process(void* start_eip, uint8_t* image, size_t image_size, bool system
     , attr { .system = system }
     , pid { max_pid++ }
 {
-    k_esp = (char*)k_malloc(THREAD_KERNEL_STACK_SIZE);
+    // TODO: allocate low mem
+    k_esp = (void*)page_to_phys_addr(alloc_n_raw_pages(2));
     memset((char*)k_esp, 0x00, THREAD_KERNEL_STACK_SIZE);
-    k_esp = align_down_to_16byte((char*)k_esp + THREAD_KERNEL_STACK_SIZE);
+    k_esp = (char*)k_esp + THREAD_KERNEL_STACK_SIZE;
 
     auto thd = thds.emplace_back(thread {
         .eip = start_eip,
@@ -137,11 +152,46 @@ process::process(void* start_eip, uint8_t* image, size_t image_size, bool system
     }
 }
 
+void _example_io_thread(void* _d)
+{
+    const char* data = reinterpret_cast<const char*>(_d);
+    tty_print(console, data);
+    // syscall_sleep
+    asm volatile("movl $0x02, %%eax\nint $0x80":::"eax");
+}
+
 void kernel_threadd_main(void)
 {
     tty_print(console, "kernel thread daemon started\n");
-    for (;;)
+    kthreadd_new_thd_func = _example_io_thread;
+    kthreadd_new_thd_data = (void*)"data in io thread\n";
+    for (;;) {
+        spin_lock(&kthreadd_lock);
+
+        if (kthreadd_new_thd_func) {
+            int return_value = 0;
+
+            void (*func)(void*) = kthreadd_new_thd_func;
+            void* data = kthreadd_new_thd_data;
+            kthreadd_new_thd_func = nullptr;
+            kthreadd_new_thd_data = nullptr;
+
+            spin_unlock(&kthreadd_lock);
+
+            // syscall_fork
+            asm volatile("movl $0x00, %%eax\nint $0x80\nmovl %%eax, %0": "=a" (return_value): :);
+
+            if (return_value != 0) {
+                // child
+                func(data);
+                for (;;) asm_hlt();
+                // TODO: syscall_exit()
+            }
+        } else {
+            spin_unlock(&kthreadd_lock);
+        }
         asm_hlt();
+    }
 }
 
 void NORETURN init_scheduler()
@@ -212,9 +262,9 @@ void add_to_ready_list(thread* thd)
 
 static inline void next_task(const types::list<thread*>::iterator_type& iter_to_remove, thread* cur_thd)
 {
-        ready_thds->erase(iter_to_remove);
-        if (cur_thd->attr.ready)
-            ready_thds->push_back(cur_thd);
+    ready_thds->erase(iter_to_remove);
+    if (cur_thd->attr.ready)
+        ready_thds->push_back(cur_thd);
 }
 
 void do_scheduling(interrupt_stack* intrpt_data)