From 962732f5355bb3d4980d69a0ac363cac975c6f7a Mon Sep 17 00:00:00 2001 From: minhokim Date: Sat, 6 Dec 2025 21:00:33 +0900 Subject: [PATCH 1/3] feat: mmap + munmap --- pintos/include/userprog/process.h | 1 + pintos/include/vm/file.h | 2 + pintos/include/vm/vm.h | 1 + pintos/userprog/exception.c | 10 +++ pintos/userprog/process.c | 5 +- pintos/userprog/syscall.c | 29 +++++++- pintos/vm/file.c | 120 ++++++++++++++++++++++++++---- 7 files changed, 152 insertions(+), 16 deletions(-) diff --git a/pintos/include/userprog/process.h b/pintos/include/userprog/process.h index ece3420..3167ebd 100644 --- a/pintos/include/userprog/process.h +++ b/pintos/include/userprog/process.h @@ -9,6 +9,7 @@ int process_exec (void *f_name); int process_wait (tid_t); void process_exit (void); void process_activate (struct thread *next); +bool lazy_load_segment(struct page *page, void *aux); #endif /* userprog/process.h */ diff --git a/pintos/include/vm/file.h b/pintos/include/vm/file.h index cf1b8b4..56e4b17 100644 --- a/pintos/include/vm/file.h +++ b/pintos/include/vm/file.h @@ -3,10 +3,12 @@ #include "filesys/file.h" #include "vm/vm.h" + struct page; enum vm_type; struct file_page { + void *aux; }; void vm_file_init (void); diff --git a/pintos/include/vm/vm.h b/pintos/include/vm/vm.h index 3d0da9e..0d1e14f 100644 --- a/pintos/include/vm/vm.h +++ b/pintos/include/vm/vm.h @@ -51,6 +51,7 @@ struct page { /* Your implementation */ struct hash_elem hash_elem; bool writable; + unsigned page_length; /* Per-type data are binded into the union. * Each function automatically detects the current union */ diff --git a/pintos/userprog/exception.c b/pintos/userprog/exception.c index bc3760f..e5b9ef2 100644 --- a/pintos/userprog/exception.c +++ b/pintos/userprog/exception.c @@ -7,6 +7,7 @@ #include "threads/vaddr.h" #include "intrinsic.h" + /* Number of page faults processed. */ static long long page_fault_cnt; @@ -153,6 +154,15 @@ page_fault (struct intr_frame *f) { return; } + /* my_entry가 NULL이 아닌지 확인하는 안전장치가 있으면 좋습니다. */ + + if (thread_current()->my_entry != NULL) { + thread_current()->my_entry->exit_status = -1; + } + + thread_exit(); + + /* Count page faults. */ page_fault_cnt++; diff --git a/pintos/userprog/process.c b/pintos/userprog/process.c index 7af0d1a..dfe58b8 100644 --- a/pintos/userprog/process.c +++ b/pintos/userprog/process.c @@ -600,7 +600,10 @@ bool lazy_load_segment(struct page *page, void *aux) { if (success) memset(kva + info->page_read_bytes, 0, info->page_zero_bytes); - free (info); + if (page->operations->type != VM_FILE) { + free(info); + } + return true; } diff --git a/pintos/userprog/syscall.c b/pintos/userprog/syscall.c index dacc945..2de1959 100644 --- a/pintos/userprog/syscall.c +++ b/pintos/userprog/syscall.c @@ -50,6 +50,8 @@ static void syscall_seek(int fd, unsigned position); static unsigned syscall_tell(int fd); static void syscall_close(int fd); static int syscall_dup2(int oldfd, int newfd); +static void *syscall_mmap(void *addr, size_t length, int writable, int fd, off_t offset); +static void sys_munmap (void *addr); void syscall_init(void) { write_msr(MSR_STAR, ((uint64_t)SEL_UCSEG - 0x10) << 48 | ((uint64_t)SEL_KCSEG) << 32); @@ -65,7 +67,7 @@ void syscall_init(void) { /* The main system call interface */ void syscall_handler(struct intr_frame* f) { thread_current()->tf = *f; - uint64_t arg1 = f->R.rdi, arg2 = f->R.rsi, arg3 = f->R.rdx; + uint64_t arg1 = f->R.rdi, arg2 = f->R.rsi, arg3 = f->R.rdx, arg4 = f->R.r10, arg5 = f->R.r8; switch (f->R.rax) { case SYS_HALT: syscall_halt(); @@ -112,6 +114,12 @@ void syscall_handler(struct intr_frame* f) { case SYS_DUP2: f->R.rax = syscall_dup2(arg1, arg2); break; + case SYS_MMAP: + f->R.rax = syscall_mmap(arg1, arg2, arg3, arg4, arg5); + break; + case SYS_MUNMAP: + sys_munmap(arg1); + break; } } @@ -260,3 +268,22 @@ static int syscall_dup2(int oldfd, int newfd) { lock_release(&file_lock); return result; } + +static void *syscall_mmap(void *addr, size_t length, int writable, int fd, off_t offset) { + struct file *file; + + if (fd == 0 || fd == 1) { + return NULL; + } + + file = get_fd_entry(thread_current(), fd); + if (file == NULL) { + return NULL; + } + + return do_mmap(addr, length, writable, file, offset); +} + +static void sys_munmap (void *addr) { + do_munmap(addr); +} diff --git a/pintos/vm/file.c b/pintos/vm/file.c index 5f7eba9..b12f285 100644 --- a/pintos/vm/file.c +++ b/pintos/vm/file.c @@ -1,6 +1,11 @@ /* file.c: Implementation of memory backed file object (mmaped object). */ #include "vm/vm.h" +#include "threads/vaddr.h" +#include "userprog/process.h" +#include "threads/malloc.h" +#include "threads/mmu.h" + static bool file_backed_swap_in (struct page *page, void *kva); static bool file_backed_swap_out (struct page *page); @@ -19,13 +24,16 @@ void vm_file_init (void) { } -/* Initialize the file backed page */ -bool -file_backed_initializer (struct page *page, enum vm_type type, void *kva) { - /* Set up the handler */ +bool file_backed_initializer (struct page *page, enum vm_type type, void *kva) { page->operations = &file_ops; + lazy_load_info *aux; + + aux = page->uninit.aux; struct file_page *file_page = &page->file; + file_page->aux = aux; + + return true; } /* Swap in the page by read contents from the file. */ @@ -40,19 +48,103 @@ file_backed_swap_out (struct page *page) { struct file_page *file_page UNUSED = &page->file; } -/* Destory the file backed page. PAGE will be freed by the caller. */ -static void -file_backed_destroy (struct page *page) { - struct file_page *file_page UNUSED = &page->file; + +static void file_backed_destroy (struct page *page) { + struct file_page *file_page = &page->file; + lazy_load_info *aux = file_page->aux; + + if (page->frame != NULL && pml4_is_dirty(thread_current()->pml4, page->va)) { + file_write_at(aux->file, page->frame->kva, aux->page_read_bytes, aux->ofs); + pml4_set_dirty(thread_current()->pml4, page->va, 0); + } + + if (aux->file) { + file_close(aux->file); + } + + free(aux); } -/* Do the mmap */ -void * -do_mmap (void *addr, size_t length, int writable, - struct file *file, off_t offset) { +void *do_mmap (void *addr, size_t length, int writable, struct file *file, off_t offset) { + void *cur = addr; + unsigned count = 0; + struct page *head_page = NULL; + + if (addr == 0 || length == 0 || addr == NULL || pg_ofs(cur) || pg_ofs(offset)) { + return NULL; + } + + while (cur - addr < length) { + + if (is_kernel_vaddr(cur) || spt_find_page(&thread_current()->spt, cur) != NULL) { + return NULL; + } + + cur += PGSIZE; + count++; + } + + cur = addr; + while (length > 0) { + struct lazy_load_info* aux = malloc(sizeof *aux); + size_t page_read_bytes = length < PGSIZE ? length : PGSIZE; + size_t page_zero_bytes = PGSIZE - page_read_bytes; + + if (aux == NULL) + return NULL; + + aux->file = file_reopen(file); + + if (aux->file == NULL) { + free(aux); + return NULL; + } + + aux->ofs = offset; + aux->page_read_bytes = page_read_bytes; + aux->page_zero_bytes = page_zero_bytes; + + if (!vm_alloc_page_with_initializer(VM_FILE, cur, writable, lazy_load_segment, aux)) { + file_close(aux->file); + free(aux); + return NULL; + } + + if (cur == addr) { + head_page = spt_find_page(&thread_current()->spt, addr); + head_page->page_length = count; + } + + cur += PGSIZE; + offset += page_read_bytes; + length -= page_read_bytes; + } + + return addr; } /* Do the munmap */ -void -do_munmap (void *addr) { +void do_munmap (void *addr) { + + struct page *head_page; + void *current; + unsigned count; + struct supplemental_page_table *spt; + + + spt = &thread_current()->spt; + head_page = spt_find_page(spt, addr); + if (head_page == NULL) { + return; + } + + count = head_page->page_length; + current = addr; + + for (int i = 0; i < count; i++) { + + if (spt_remove_page(spt, spt_find_page(spt, current))) { + current += PGSIZE; + } + } } From a5060cf9a19ef417c20447be35280418c4b871c4 Mon Sep 17 00:00:00 2001 From: minhokim Date: Sat, 6 Dec 2025 21:54:07 +0900 Subject: [PATCH 2/3] refactoring: mmap + munmap --- pintos/userprog/syscall.c | 7 ++++++- pintos/vm/file.c | 13 ++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pintos/userprog/syscall.c b/pintos/userprog/syscall.c index 2de1959..8204059 100644 --- a/pintos/userprog/syscall.c +++ b/pintos/userprog/syscall.c @@ -280,10 +280,15 @@ static void *syscall_mmap(void *addr, size_t length, int writable, int fd, off_t if (file == NULL) { return NULL; } - + + if (addr == 0 || length == 0 || addr == NULL || pg_ofs(addr) || pg_ofs(offset)) { + return NULL; + } + return do_mmap(addr, length, writable, file, offset); } static void sys_munmap (void *addr) { + do_munmap(addr); } diff --git a/pintos/vm/file.c b/pintos/vm/file.c index b12f285..4ceb92c 100644 --- a/pintos/vm/file.c +++ b/pintos/vm/file.c @@ -70,10 +70,6 @@ void *do_mmap (void *addr, size_t length, int writable, struct file *file, off_t unsigned count = 0; struct page *head_page = NULL; - if (addr == 0 || length == 0 || addr == NULL || pg_ofs(cur) || pg_ofs(offset)) { - return NULL; - } - while (cur - addr < length) { if (is_kernel_vaddr(cur) || spt_find_page(&thread_current()->spt, cur) != NULL) { @@ -123,7 +119,6 @@ void *do_mmap (void *addr, size_t length, int writable, struct file *file, off_t return addr; } -/* Do the munmap */ void do_munmap (void *addr) { struct page *head_page; @@ -131,7 +126,6 @@ void do_munmap (void *addr) { unsigned count; struct supplemental_page_table *spt; - spt = &thread_current()->spt; head_page = spt_find_page(spt, addr); if (head_page == NULL) { @@ -142,9 +136,10 @@ void do_munmap (void *addr) { current = addr; for (int i = 0; i < count; i++) { - - if (spt_remove_page(spt, spt_find_page(spt, current))) { - current += PGSIZE; + struct page *page = spt_find_page(spt, current); + if (page != NULL) { + spt_remove_page(spt, page); } + current += PGSIZE; } } From 9bfe8d603d12000f5b1f58f33f89c328a4456288 Mon Sep 17 00:00:00 2001 From: minhokim Date: Mon, 8 Dec 2025 16:00:15 +0900 Subject: [PATCH 3/3] refactoring: lazy + vm_type --- pintos/userprog/process.c | 8 ++++---- pintos/vm/file.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pintos/userprog/process.c b/pintos/userprog/process.c index dfe58b8..3dc3e30 100644 --- a/pintos/userprog/process.c +++ b/pintos/userprog/process.c @@ -600,10 +600,10 @@ bool lazy_load_segment(struct page *page, void *aux) { if (success) memset(kva + info->page_read_bytes, 0, info->page_zero_bytes); - if (page->operations->type != VM_FILE) { - free(info); - } - + + if (VM_TYPE(page->uninit.type) != VM_FILE) + free(info); + return true; } diff --git a/pintos/vm/file.c b/pintos/vm/file.c index 4ceb92c..4c4772e 100644 --- a/pintos/vm/file.c +++ b/pintos/vm/file.c @@ -53,7 +53,7 @@ static void file_backed_destroy (struct page *page) { struct file_page *file_page = &page->file; lazy_load_info *aux = file_page->aux; - if (page->frame != NULL && pml4_is_dirty(thread_current()->pml4, page->va)) { + if (pml4_is_dirty(thread_current()->pml4, page->va)) { file_write_at(aux->file, page->frame->kva, aux->page_read_bytes, aux->ofs); pml4_set_dirty(thread_current()->pml4, page->va, 0); }