feature: fork() (to be tested)
This commit is contained in:
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
;
|
;
|
||||||
|
|||||||
@ -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"); */
|
||||||
|
|||||||
@ -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);
|
||||||
@ -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;
|
||||||
@ -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) {
|
||||||
@ -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;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -5,5 +5,5 @@
|
|||||||
void heap_cmd(char *arg)
|
void heap_cmd(char *arg)
|
||||||
{
|
{
|
||||||
(void)arg;
|
(void)arg;
|
||||||
show_valloc_mem();
|
show_ualloc_mem();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user