From 452a824e9d87049556e903a3292a99c466e2f0a4 Mon Sep 17 00:00:00 2001 From: liguo <2925441676@qq.com> Date: Sun, 25 Feb 2024 22:54:38 +0800 Subject: [PATCH] init commit of lab3_challenge3 --- Makefile | 2 +- kernel/process.c | 50 ++++++++++++++++++++------------------- kernel/syscall.c | 8 +++++++ kernel/syscall.h | 2 +- user/app_cow.c | 25 ++++++++++++++++++++ user/app_two_long_loops.c | 28 ---------------------- user/user_lib.c | 5 ++++ user/user_lib.h | 1 + 8 files changed, 67 insertions(+), 54 deletions(-) create mode 100644 user/app_cow.c delete mode 100644 user/app_two_long_loops.c diff --git a/Makefile b/Makefile index 2dde5bf..6413db2 100644 --- a/Makefile +++ b/Makefile @@ -70,7 +70,7 @@ USER_OBJS := $(addprefix $(OBJ_DIR)/, $(patsubst %.c,%.o,$(USER_CPPS))) -USER_TARGET := $(OBJ_DIR)/app_two_long_loops +USER_TARGET := $(OBJ_DIR)/app_cow #------------------------targets------------------------ $(OBJ_DIR): @-mkdir -p $(OBJ_DIR) diff --git a/kernel/process.c b/kernel/process.c index f4c74b6..3dfe7f4 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -196,31 +196,33 @@ int do_fork( process* parent) // convert free_pages_address into a filter to skip reclaimed blocks in the heap // when mapping the heap blocks - int free_block_filter[MAX_HEAP_PAGES]; - memset(free_block_filter, 0, MAX_HEAP_PAGES); - uint64 heap_bottom = parent->user_heap.heap_bottom; - for (int i = 0; i < parent->user_heap.free_pages_count; i++) { - int index = (parent->user_heap.free_pages_address[i] - heap_bottom) / PGSIZE; - free_block_filter[index] = 1; + { + int free_block_filter[MAX_HEAP_PAGES]; + memset(free_block_filter, 0, MAX_HEAP_PAGES); + uint64 heap_bottom = parent->user_heap.heap_bottom; + for (int i = 0; i < parent->user_heap.free_pages_count; i++) { + int index = (parent->user_heap.free_pages_address[i] - heap_bottom) / PGSIZE; + free_block_filter[index] = 1; + } + + // copy and map the heap blocks + for (uint64 heap_block = current->user_heap.heap_bottom; + heap_block < current->user_heap.heap_top; heap_block += PGSIZE) { + if (free_block_filter[(heap_block - heap_bottom) / PGSIZE]) // skip free blocks + continue; + + void* child_pa = alloc_page(); + memcpy(child_pa, (void*)lookup_pa(parent->pagetable, heap_block), PGSIZE); + user_vm_map((pagetable_t)child->pagetable, heap_block, PGSIZE, (uint64)child_pa, + prot_to_type(PROT_WRITE | PROT_READ, 1)); + } + + child->mapped_info[HEAP_SEGMENT].npages = parent->mapped_info[HEAP_SEGMENT].npages; + + // copy the heap manager from parent to child + memcpy((void*)&child->user_heap, (void*)&parent->user_heap, sizeof(parent->user_heap)); + break; } - - // copy and map the heap blocks - for (uint64 heap_block = current->user_heap.heap_bottom; - heap_block < current->user_heap.heap_top; heap_block += PGSIZE) { - if (free_block_filter[(heap_block - heap_bottom) / PGSIZE]) // skip free blocks - continue; - - void* child_pa = alloc_page(); - memcpy(child_pa, (void*)lookup_pa(parent->pagetable, heap_block), PGSIZE); - user_vm_map((pagetable_t)child->pagetable, heap_block, PGSIZE, (uint64)child_pa, - prot_to_type(PROT_WRITE | PROT_READ, 1)); - } - - child->mapped_info[HEAP_SEGMENT].npages = parent->mapped_info[HEAP_SEGMENT].npages; - - // copy the heap manager from parent to child - memcpy((void*)&child->user_heap, (void*)&parent->user_heap, sizeof(parent->user_heap)); - break; case CODE_SEGMENT: // TODO (lab3_1): implment the mapping of child code segment to parent's // code segment. diff --git a/kernel/syscall.c b/kernel/syscall.c index d6591c4..ce9309d 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -93,6 +93,12 @@ ssize_t sys_user_yield() { return 0; } +ssize_t sys_user_printpa(uint64 va) +{ + uint64 pa = (uint64)user_va_to_pa((pagetable_t)(current->pagetable), (void*)va); + sprint("%lx\n", pa); + return 0; +} // // [a0]: the syscall number; [a1] ... [a7]: arguments to the syscalls. @@ -113,6 +119,8 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, l return sys_user_fork(); case SYS_user_yield: return sys_user_yield(); + case SYS_user_printpa: + return sys_user_printpa(a1); default: panic("Unknown syscall %ld \n", a0); } diff --git a/kernel/syscall.h b/kernel/syscall.h index e0a1a16..cfe9ce5 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -14,7 +14,7 @@ // added @lab3_1 #define SYS_user_fork (SYS_user_base + 4) #define SYS_user_yield (SYS_user_base + 5) - +#define SYS_user_printpa (SYS_user_base + 6) long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7); #endif diff --git a/user/app_cow.c b/user/app_cow.c new file mode 100644 index 0000000..ca5974a --- /dev/null +++ b/user/app_cow.c @@ -0,0 +1,25 @@ +/* + * This app fork a child process to read and write the heap data from parent process. + * Because implemented copy on write, when child process only read the heap data, + * the physical address is the same as the parent process. + * But after writing, child process heap will have different physical address. + */ + +#include "user/user_lib.h" +#include "util/types.h" + +int main(void) { + int *heap_data = naive_malloc(); + printu("the physical address of parent process heap is: "); + printpa(heap_data); + int pid = fork(); + if (pid == 0) { + printu("the physical address of child process heap before copy on write is: "); + printpa(heap_data); + heap_data[0] = 0; + printu("the physical address of child process heap after copy on write is: "); + printpa(heap_data); + } + exit(0); + return 0; +} diff --git a/user/app_two_long_loops.c b/user/app_two_long_loops.c deleted file mode 100644 index 2568485..0000000 --- a/user/app_two_long_loops.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * The application of lab3_3. - * parent and child processes never give up their processor during execution. - */ - -#include "user/user_lib.h" -#include "util/types.h" - -int main(void) { - uint64 pid = fork(); - uint64 rounds = 100000000; - uint64 interval = 10000000; - uint64 a = 0; - if (pid == 0) { - printu("Child: Hello world! \n"); - for (uint64 i = 0; i < rounds; ++i) { - if (i % interval == 0) printu("Child running %ld \n", i); - } - } else { - printu("Parent: Hello world! \n"); - for (uint64 i = 0; i < rounds; ++i) { - if (i % interval == 0) printu("Parent running %ld \n", i); - } - } - - exit(0); - return 0; -} diff --git a/user/user_lib.c b/user/user_lib.c index 3fcb85d..2993d3f 100644 --- a/user/user_lib.c +++ b/user/user_lib.c @@ -76,3 +76,8 @@ int fork() { void yield() { do_user_call(SYS_user_yield, 0, 0, 0, 0, 0, 0, 0); } + +void printpa(int* va) +{ + do_user_call(SYS_user_printpa, (uint64)va, 0, 0, 0, 0, 0, 0); +} \ No newline at end of file diff --git a/user/user_lib.h b/user/user_lib.h index 63e2e25..e36cf14 100644 --- a/user/user_lib.h +++ b/user/user_lib.h @@ -8,3 +8,4 @@ void* naive_malloc(); void naive_free(void* va); int fork(); void yield(); +void printpa(int* va); \ No newline at end of file