feature: fork() (to be tested)

This commit is contained in:
0x35c
2025-11-30 13:32:24 +01:00
parent 6ff044c07a
commit cde3702132
16 changed files with 113 additions and 36 deletions

View File

@ -75,10 +75,10 @@ int new_vzone(block_type_t type, size_t size);
int new_kzone(block_type_t type, size_t size); int new_kzone(block_type_t type, size_t size);
/*----------------------------*/ /*----------------------------*/
void *vmalloc(size_t size); void *umalloc(size_t size);
void vfree(void *ptr); void ufree(void *ptr);
void *vrealloc(void *ptr, size_t size); void *vrealloc(void *ptr, size_t size);
void show_valloc_mem(void); void show_ualloc_mem(void);
size_t vsize(void *virt_addr); size_t vsize(void *virt_addr);
void *kmalloc(size_t size); void *kmalloc(size_t size);
void kfree(void *ptr); void kfree(void *ptr);

View File

@ -29,7 +29,8 @@
#define PDE_MULTIBOOT 1020 #define PDE_MULTIBOOT 1020
#define GET_PTE(pd_index, pt_index) \ #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) \ #define PTE2VA(pd_index, pt_index) \
((uint32_t *)((((uint32_t)pd_index * 1024) + (uint32_t)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); void *alloc_frame(void);
int free_frame(void *frame_ptr); int free_frame(void *frame_ptr);
void *kalloc_pages(size_t nb_pages); void *kalloc_pages(size_t nb_pages);
void *valloc_pages(size_t nb_pages); void *ualloc_pages(size_t nb_pages);
int kfree_pages(void *page_ptr, size_t size); int kfree_pages(void *page_ptr, size_t nb_pages);
int vfree_pages(void *page_ptr, size_t size); int ufree_pages(void *page_ptr, size_t nb_pages);

View File

@ -28,5 +28,5 @@ struct pcb {
void switch_process(struct pcb *next_pcb); void switch_process(struct pcb *next_pcb);
struct pcb *create_process(uid_t uid); struct pcb *create_process(uid_t uid);
// int8_t create_kernel_process(void);
void remove_process(struct pcb *pcb); void remove_process(struct pcb *pcb);
pid_t fork(void);

View File

@ -40,7 +40,7 @@ static void clock_handler(struct registers *regs)
{ {
scheduler_counter++; scheduler_counter++;
sleep_counter--; sleep_counter--;
if (scheduler_counter % 100 == 0) if (scheduler_counter % 30 == 0)
scheduler((uint32_t *)regs); scheduler((uint32_t *)regs);
} }

View File

@ -33,9 +33,11 @@
static void uwu(void) static void uwu(void)
{ {
pid_t pid = fork();
kprintf("pid: %d\n", pid);
while (1) { while (1) {
// sleep(1000); // 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(); load_drivers();
terminal_initialize(); terminal_initialize();
create_process(1); create_process(1);
create_thread(current_pcb, shell_init); // create_thread(current_pcb, shell_init);
create_process(2); create_thread(current_pcb, uwu);
create_thread(current_pcb->next, uwu);
toris(); toris();
while (true) while (true)
; ;

View File

@ -27,7 +27,7 @@ __attribute__((noreturn)) void kpanic(const char *format, ...)
kprintf("fault at address: %p\n", faulting_address); kprintf("fault at address: %p\n", faulting_address);
// for (int i = 16; i < 32; i++) // for (int i = 16; i < 32; i++)
// kprintf("%p\n", page_table1[i]); // kprintf("%p\n", page_table1[i]);
// show_valloc_mem(); // show_ualloc_mem();
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* print_stack(); */ /* print_stack(); */
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */

View File

@ -51,7 +51,7 @@ static void new_block(Zone *zone, uint32_t zone_size)
int new_vzone(block_type_t type, uint32_t size) int new_vzone(block_type_t type, uint32_t size)
{ {
// assert(current_task->pid); // assert(current_task->pid);
void *heap = valloc_pages(CEIL(size, PAGE_SIZE)); void *heap = ualloc_pages(CEIL(size, PAGE_SIZE));
if (heap == NULL) { if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_pages failed\n"); kprintf(KERN_ERR "error: alloc_pages failed\n");
return (-1); return (-1);

View File

@ -5,7 +5,7 @@
// FULL_INFO is to display (or not) both used and unused blocks // FULL_INFO is to display (or not) both used and unused blocks
#define FULL_INFO 1 #define FULL_INFO 1
void show_valloc_mem(void) void show_ualloc_mem(void)
{ {
char *const zones_name[3] = {"TINY", "SMALL", "LARGE"}; char *const zones_name[3] = {"TINY", "SMALL", "LARGE"};
uint32_t total_size = 0; uint32_t total_size = 0;

View File

@ -40,7 +40,7 @@ static uint32_t *find_next_block(size_t nb_pages)
return NULL; return NULL;
} }
void *valloc_pages(size_t nb_pages) void *ualloc_pages(size_t nb_pages)
{ {
uint32_t *start = find_next_block(nb_pages); uint32_t *start = find_next_block(nb_pages);
if (!start) if (!start)
@ -60,7 +60,7 @@ void *valloc_pages(size_t nb_pages)
return PTE2VA(page_index / 1024, page_index % 1024); 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; const uint32_t page_addr = (uint32_t)page_ptr;
if (page_addr % PAGE_SIZE) { if (page_addr % PAGE_SIZE) {

View File

@ -47,7 +47,7 @@ static int unmap_zone(Zone *zone)
if (right) if (right)
right->prev = left; right->prev = left;
unmap: unmap:
err = vfree_pages((void *)zone, zone->size); err = ufree_pages((void *)zone, zone->size);
if (err) if (err)
kprintf(KERN_ERR "error: munmap failed\n"); kprintf(KERN_ERR "error: munmap failed\n");
return (err); return (err);
@ -94,7 +94,7 @@ static int add_available(Block *available, Block *merged)
* newly merged block * newly merged block
* Finally, we add the block to the list of available blocks * Finally, we add the block to the list of available blocks
*/ */
void vfree(void *ptr) void ufree(void *ptr)
{ {
if (ptr == NULL) if (ptr == NULL)
return; return;

View File

@ -33,7 +33,7 @@ static Block *find_block(Zone *head, uint32_t size)
* After the allocation, this will become * After the allocation, this will become
* ... -> [5] -> [new] -> [6] -> ... * ... -> [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: * Let's say the metadata takes a size of 2:
* ... -> [metadata][data][remaining size] -> [6] * ... -> [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) * ptr: returns the aligned pointer of the block (after the metadata)
*/ */
void *vmalloc(uint32_t size) void *umalloc(uint32_t size)
{ {
void *ptr = NULL; void *ptr = NULL;
if (size == 0) { if (size == 0) {
kprintf(KERN_WARNING "vmalloc: can't vmalloc(0)\n"); kprintf(KERN_WARNING "umalloc: can't umalloc(0)\n");
return NULL; return NULL;
} }

View File

@ -2,9 +2,9 @@
#include "string.h" #include "string.h"
#include <stdint.h> #include <stdint.h>
// Prototype for kfree and vmalloc // Prototype for kfree and umalloc
void kfree(void *ptr); void kfree(void *ptr);
void *vmalloc(uint32_t size); void *umalloc(uint32_t size);
/* /*
* ptr: block to resize (undefined behavior if invalid) * ptr: block to resize (undefined behavior if invalid)
@ -28,10 +28,10 @@ void *vrealloc(void *ptr, uint32_t size)
block->sub_size = size; block->sub_size = size;
return (ptr); return (ptr);
} }
new_ptr = vmalloc(size); new_ptr = umalloc(size);
if (new_ptr == NULL) if (new_ptr == NULL)
return NULL; return NULL;
memmove(new_ptr, ptr, block->size); memmove(new_ptr, ptr, block->size);
vfree(ptr); ufree(ptr);
return (new_ptr); return (new_ptr);
} }

View File

@ -6,7 +6,7 @@
static struct tcb *thread_clone(struct tcb *thread) 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) if (!new_tcb)
return NULL; return NULL;
new_tcb->tid = thread->tid; new_tcb->tid = thread->tid;
@ -19,20 +19,95 @@ static struct tcb *thread_clone(struct tcb *thread)
return new_tcb; 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) pid_t fork(void)
{ {
struct pcb *new_pcb = create_process(current_pcb->uid); struct pcb *new_pcb = create_process(current_pcb->uid);
if (!new_pcb) if (!new_pcb)
return -1; return -1;
struct list *new_node = vmalloc(sizeof(struct list)); struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) { if (!new_node) {
remove_process(new_pcb); remove_process(new_pcb);
return -1; return -1;
} }
new_pcb->daddy = current_pcb; new_pcb->daddy = current_pcb;
lst_add_back(&new_pcb->children, new_node); 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;
} }

View File

@ -18,9 +18,9 @@ struct tcb *create_thread(struct pcb *process, void (*entry)(void))
memcpy(PD, process->heap, memcpy(PD, process->heap,
(USER_PT_END - USER_PT_START) * sizeof(uint32_t)); (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) { if (!new_tcb->esp0) {
vfree(new_tcb); ufree(new_tcb);
return NULL; return NULL;
} }
memcpy(process->heap, PD, 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)); struct list *new_node = kmalloc(sizeof(struct list));
if (!new_node) { if (!new_node) {
kfree_pages(new_tcb->esp0, STACK_SIZE); kfree_pages(new_tcb->esp0, STACK_SIZE);
vfree(new_tcb); ufree(new_tcb);
return NULL; return NULL;
} }
new_node->content = new_tcb; new_node->content = new_tcb;

View File

@ -5,5 +5,5 @@
void heap_cmd(char *arg) void heap_cmd(char *arg)
{ {
(void)arg; (void)arg;
show_valloc_mem(); show_ualloc_mem();
} }