From cde3702132ae0c91a5a2552fb080de40ceef9aff Mon Sep 17 00:00:00 2001 From: 0x35c <> Date: Sun, 30 Nov 2025 13:32:24 +0100 Subject: [PATCH] feature: fork() (to be tested) --- headers/alloc.h | 6 +- headers/memory.h | 9 +-- headers/process.h | 2 +- src/drivers/clock.c | 2 +- src/kernel.c | 9 +-- src/kpanic.c | 2 +- src/memory/{virt => user}/allocator.c | 2 +- src/memory/{virt => user}/info.c | 2 +- src/memory/{virt => user}/page.c | 4 +- src/memory/{virt => user}/vfree.c | 4 +- src/memory/{virt => user}/vmalloc.c | 6 +- src/memory/{virt => user}/vrealloc.c | 8 +-- src/memory/{virt => user}/vsize.c | 0 src/multitasking/fork.c | 85 +++++++++++++++++++++++++-- src/multitasking/thread.c | 6 +- src/shell/commands/heap_cmd.c | 2 +- 16 files changed, 113 insertions(+), 36 deletions(-) rename src/memory/{virt => user}/allocator.c (96%) rename src/memory/{virt => user}/info.c (98%) rename src/memory/{virt => user}/page.c (94%) rename src/memory/{virt => user}/vfree.c (97%) rename src/memory/{virt => user}/vmalloc.c (96%) rename src/memory/{virt => user}/vrealloc.c (89%) rename src/memory/{virt => user}/vsize.c (100%) diff --git a/headers/alloc.h b/headers/alloc.h index 2a852e4..ac52a06 100644 --- a/headers/alloc.h +++ b/headers/alloc.h @@ -75,10 +75,10 @@ int new_vzone(block_type_t type, size_t size); int new_kzone(block_type_t type, size_t size); /*----------------------------*/ -void *vmalloc(size_t size); -void vfree(void *ptr); +void *umalloc(size_t size); +void ufree(void *ptr); void *vrealloc(void *ptr, size_t size); -void show_valloc_mem(void); +void show_ualloc_mem(void); size_t vsize(void *virt_addr); void *kmalloc(size_t size); void kfree(void *ptr); diff --git a/headers/memory.h b/headers/memory.h index 5a4686d..5b81b42 100644 --- a/headers/memory.h +++ b/headers/memory.h @@ -29,7 +29,8 @@ #define PDE_MULTIBOOT 1020 #define GET_PTE(pd_index, pt_index) \ - ((uint32_t *)(VIRT_PT_BASE + ((uint32_t) pd_index) * 4096 + ((uint32_t) pt_index) * 4)) + ((uint32_t *)(VIRT_PT_BASE + ((uint32_t)pd_index) * 4096 + \ + ((uint32_t)pt_index) * 4)) #define PTE2VA(pd_index, pt_index) \ ((uint32_t *)((((uint32_t)pd_index * 1024) + (uint32_t)pt_index) * \ @@ -74,6 +75,6 @@ void init_memory(void); void *alloc_frame(void); int free_frame(void *frame_ptr); void *kalloc_pages(size_t nb_pages); -void *valloc_pages(size_t nb_pages); -int kfree_pages(void *page_ptr, size_t size); -int vfree_pages(void *page_ptr, size_t size); +void *ualloc_pages(size_t nb_pages); +int kfree_pages(void *page_ptr, size_t nb_pages); +int ufree_pages(void *page_ptr, size_t nb_pages); diff --git a/headers/process.h b/headers/process.h index b2dc0b9..4330783 100644 --- a/headers/process.h +++ b/headers/process.h @@ -28,5 +28,5 @@ struct pcb { void switch_process(struct pcb *next_pcb); struct pcb *create_process(uid_t uid); -// int8_t create_kernel_process(void); void remove_process(struct pcb *pcb); +pid_t fork(void); diff --git a/src/drivers/clock.c b/src/drivers/clock.c index 3ba1213..e85ed13 100644 --- a/src/drivers/clock.c +++ b/src/drivers/clock.c @@ -40,7 +40,7 @@ static void clock_handler(struct registers *regs) { scheduler_counter++; sleep_counter--; - if (scheduler_counter % 100 == 0) + if (scheduler_counter % 30 == 0) scheduler((uint32_t *)regs); } diff --git a/src/kernel.c b/src/kernel.c index 03b9499..2100145 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -33,9 +33,11 @@ static void uwu(void) { + pid_t pid = fork(); + kprintf("pid: %d\n", pid); while (1) { // sleep(1000); - kprintf("uwu\n"); + // kprintf("%d\n", current_pcb->pid); } } @@ -55,9 +57,8 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic) load_drivers(); terminal_initialize(); create_process(1); - create_thread(current_pcb, shell_init); - create_process(2); - create_thread(current_pcb->next, uwu); + // create_thread(current_pcb, shell_init); + create_thread(current_pcb, uwu); toris(); while (true) ; diff --git a/src/kpanic.c b/src/kpanic.c index a75759f..758924e 100644 --- a/src/kpanic.c +++ b/src/kpanic.c @@ -27,7 +27,7 @@ __attribute__((noreturn)) void kpanic(const char *format, ...) kprintf("fault at address: %p\n", faulting_address); // for (int i = 16; i < 32; i++) // kprintf("%p\n", page_table1[i]); - // show_valloc_mem(); + // show_ualloc_mem(); /* kprintf("\n\n"); */ /* print_stack(); */ /* kprintf("\n\n"); */ diff --git a/src/memory/virt/allocator.c b/src/memory/user/allocator.c similarity index 96% rename from src/memory/virt/allocator.c rename to src/memory/user/allocator.c index 18adbfe..fbc16b4 100644 --- a/src/memory/virt/allocator.c +++ b/src/memory/user/allocator.c @@ -51,7 +51,7 @@ static void new_block(Zone *zone, uint32_t zone_size) int new_vzone(block_type_t type, uint32_t size) { // assert(current_task->pid); - void *heap = valloc_pages(CEIL(size, PAGE_SIZE)); + void *heap = ualloc_pages(CEIL(size, PAGE_SIZE)); if (heap == NULL) { kprintf(KERN_ERR "error: alloc_pages failed\n"); return (-1); diff --git a/src/memory/virt/info.c b/src/memory/user/info.c similarity index 98% rename from src/memory/virt/info.c rename to src/memory/user/info.c index 885e87c..ab58498 100644 --- a/src/memory/virt/info.c +++ b/src/memory/user/info.c @@ -5,7 +5,7 @@ // FULL_INFO is to display (or not) both used and unused blocks #define FULL_INFO 1 -void show_valloc_mem(void) +void show_ualloc_mem(void) { char *const zones_name[3] = {"TINY", "SMALL", "LARGE"}; uint32_t total_size = 0; diff --git a/src/memory/virt/page.c b/src/memory/user/page.c similarity index 94% rename from src/memory/virt/page.c rename to src/memory/user/page.c index 747148c..1f250db 100644 --- a/src/memory/virt/page.c +++ b/src/memory/user/page.c @@ -40,7 +40,7 @@ static uint32_t *find_next_block(size_t nb_pages) return NULL; } -void *valloc_pages(size_t nb_pages) +void *ualloc_pages(size_t nb_pages) { uint32_t *start = find_next_block(nb_pages); if (!start) @@ -60,7 +60,7 @@ void *valloc_pages(size_t nb_pages) return PTE2VA(page_index / 1024, page_index % 1024); } -int vfree_pages(void *page_ptr, size_t nb_pages) +int ufree_pages(void *page_ptr, size_t nb_pages) { const uint32_t page_addr = (uint32_t)page_ptr; if (page_addr % PAGE_SIZE) { diff --git a/src/memory/virt/vfree.c b/src/memory/user/vfree.c similarity index 97% rename from src/memory/virt/vfree.c rename to src/memory/user/vfree.c index 36bff8c..848ba2b 100644 --- a/src/memory/virt/vfree.c +++ b/src/memory/user/vfree.c @@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone) if (right) right->prev = left; unmap: - err = vfree_pages((void *)zone, zone->size); + err = ufree_pages((void *)zone, zone->size); if (err) kprintf(KERN_ERR "error: munmap failed\n"); return (err); @@ -94,7 +94,7 @@ static int add_available(Block *available, Block *merged) * newly merged block * Finally, we add the block to the list of available blocks */ -void vfree(void *ptr) +void ufree(void *ptr) { if (ptr == NULL) return; diff --git a/src/memory/virt/vmalloc.c b/src/memory/user/vmalloc.c similarity index 96% rename from src/memory/virt/vmalloc.c rename to src/memory/user/vmalloc.c index 0cc2661..b75b5d1 100644 --- a/src/memory/virt/vmalloc.c +++ b/src/memory/user/vmalloc.c @@ -33,7 +33,7 @@ static Block *find_block(Zone *head, uint32_t size) * After the allocation, this will become * ... -> [5] -> [new] -> [6] -> ... * - * For an example of [5].size = 32 and requiring a vmalloc of 10 + * For an example of [5].size = 32 and requiring a umalloc of 10 * Let's say the metadata takes a size of 2: * ... -> [metadata][data][remaining size] -> [6] * ^ ^ ^ @@ -126,12 +126,12 @@ static void save_block(Zone *head, Block *block, Zone *zone) * * ptr: returns the aligned pointer of the block (after the metadata) */ -void *vmalloc(uint32_t size) +void *umalloc(uint32_t size) { void *ptr = NULL; if (size == 0) { - kprintf(KERN_WARNING "vmalloc: can't vmalloc(0)\n"); + kprintf(KERN_WARNING "umalloc: can't umalloc(0)\n"); return NULL; } diff --git a/src/memory/virt/vrealloc.c b/src/memory/user/vrealloc.c similarity index 89% rename from src/memory/virt/vrealloc.c rename to src/memory/user/vrealloc.c index 026115d..d55d98b 100644 --- a/src/memory/virt/vrealloc.c +++ b/src/memory/user/vrealloc.c @@ -2,9 +2,9 @@ #include "string.h" #include -// Prototype for kfree and vmalloc +// Prototype for kfree and umalloc void kfree(void *ptr); -void *vmalloc(uint32_t size); +void *umalloc(uint32_t size); /* * ptr: block to resize (undefined behavior if invalid) @@ -28,10 +28,10 @@ void *vrealloc(void *ptr, uint32_t size) block->sub_size = size; return (ptr); } - new_ptr = vmalloc(size); + new_ptr = umalloc(size); if (new_ptr == NULL) return NULL; memmove(new_ptr, ptr, block->size); - vfree(ptr); + ufree(ptr); return (new_ptr); } diff --git a/src/memory/virt/vsize.c b/src/memory/user/vsize.c similarity index 100% rename from src/memory/virt/vsize.c rename to src/memory/user/vsize.c diff --git a/src/multitasking/fork.c b/src/multitasking/fork.c index 17acd0f..1c453b0 100644 --- a/src/multitasking/fork.c +++ b/src/multitasking/fork.c @@ -6,7 +6,7 @@ static struct tcb *thread_clone(struct tcb *thread) { - struct tcb *new_tcb = vmalloc(sizeof(struct tcb)); + struct tcb *new_tcb = umalloc(sizeof(struct tcb)); if (!new_tcb) return NULL; new_tcb->tid = thread->tid; @@ -19,20 +19,95 @@ static struct tcb *thread_clone(struct tcb *thread) return new_tcb; } +static void free_pts(void) +{ + for (size_t i = USER_PT_END / 2; PD[i]; i++) { + uint32_t *pt = PTE2VA(1023, i); + for (size_t j = 0; j < 1024; j++) + if (pt[j]) + ufree_pages(PTE2VA(i, j), 1); + ufree_pages(pt, 1); + } +} + +static int copy_pt(uint32_t *pt_src, uint32_t *pt_dest, size_t pd_index) +{ + for (size_t i = 0; i < 1024; i++) { + if (pt_src[i]) { + pt_dest[i] = (uint32_t)alloc_frame() | INIT_FLAGS; + if (pt_dest[i] == INIT_FLAGS) { + for (size_t j = 0; j < i; j++) + free_frame( + (void *)(pt_dest[j] & PAGE_MASK)); + return -1; + } + void *src_page = PTE2VA(pd_index, i); + void *dest_page = PTE2VA(pd_index + USER_PT_END / 2, i); + memcpy(dest_page, src_page, PAGE_SIZE); + } + } + return 0; +} + +static int deep_copy(struct pcb *new_pcb) +{ + if (PD[USER_PT_END / 2]) + return -2; + size_t i; + for (i = USER_PT_START; PD[i]; i++) { + void *new_pt = alloc_frame(); + if (!new_pt) { + free_pts(); + return -1; + } + if (!copy_pt(PTE2VA(1023, i), new_pt, i)) { + free_pts(); + return -1; + } + new_pcb->heap[i] = (uint32_t)new_pt | INIT_FLAGS; + } + bzero(PD + USER_PT_END / 2, i * sizeof(uint32_t)); + return 0; +} + pid_t fork(void) { struct pcb *new_pcb = create_process(current_pcb->uid); if (!new_pcb) return -1; - struct list *new_node = vmalloc(sizeof(struct list)); + struct list *new_node = kmalloc(sizeof(struct list)); if (!new_node) { remove_process(new_pcb); return -1; } new_pcb->daddy = current_pcb; lst_add_back(&new_pcb->children, new_node); - // loop on threads clone - thread_clone(current_pcb->thread_list->content); - return new_pcb->pid; + if (deep_copy(new_pcb) < 0) + goto error; + struct list *e; + struct list *prev = NULL; + for (struct list *it = current_pcb->thread_list; it; it = it->next) { + e = kmalloc(sizeof(struct list)); + if (!e) + goto error; + if (prev) + prev->next = e; + else + new_pcb->thread_list = e; + struct tcb *new_content = kmalloc(sizeof(struct tcb)); + if (!new_content) { + kfree(e); + goto error; + } + memcpy(it->content, new_content, sizeof(struct tcb)); + new_content->process = new_pcb; + e->next = NULL; + prev = e; + } + + return current_pcb == new_pcb ? 0 : new_pcb->pid; +error: + remove_process(new_pcb); + return -1; } diff --git a/src/multitasking/thread.c b/src/multitasking/thread.c index 6647cec..a7afba3 100644 --- a/src/multitasking/thread.c +++ b/src/multitasking/thread.c @@ -18,9 +18,9 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void)) memcpy(PD, process->heap, (USER_PT_END - USER_PT_START) * sizeof(uint32_t)); - new_tcb->esp0 = valloc_pages(CEIL(STACK_SIZE, PAGE_SIZE)); + new_tcb->esp0 = ualloc_pages(CEIL(STACK_SIZE, PAGE_SIZE)); if (!new_tcb->esp0) { - vfree(new_tcb); + ufree(new_tcb); return NULL; } memcpy(process->heap, PD, @@ -54,7 +54,7 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void)) struct list *new_node = kmalloc(sizeof(struct list)); if (!new_node) { kfree_pages(new_tcb->esp0, STACK_SIZE); - vfree(new_tcb); + ufree(new_tcb); return NULL; } new_node->content = new_tcb; diff --git a/src/shell/commands/heap_cmd.c b/src/shell/commands/heap_cmd.c index 14a7c61..5e09577 100644 --- a/src/shell/commands/heap_cmd.c +++ b/src/shell/commands/heap_cmd.c @@ -5,5 +5,5 @@ void heap_cmd(char *arg) { (void)arg; - show_valloc_mem(); + show_ualloc_mem(); }