[Pintos-KAIST] Project 3 : Memory Mapped Files (+ page-merge FAIL ํ•ด๊ฒฐํ•˜๊ธฐ)

์œ ์„ ยท2024๋…„ 5์›” 21์ผ
0

Pintos - KAIST

๋ชฉ๋ก ๋ณด๊ธฐ
14/16
post-thumbnail

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB ๋ ˆํฌ์ง€ํ† ๋ฆฌ
๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB Memory Mapped Files ์ด์Šˆ

๊ณผ์ œ ์„ค๋ช…

Anonymous Memory๊ฐ€ ์•„๋‹Œ File-Backed memory = Memory Mapped Page์— ๋Œ€ํ•ด ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.

File backed page์— ์žˆ๋Š” ๋‚ด์šฉ๋ฌผ๋“ค์€ ๋ชจ๋‘ ๋””์Šคํฌ์—์„œ ์กด์žฌํ•˜๊ณ  ์žˆ๋Š” ํŒŒ์ผ์„ ๋ณต์‚ฌํ•œ ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ ํŽ˜์ด์ง€ ํดํŠธ๊ฐ€ ์ผ์–ด๋‚˜๋ฉด ๋ฐ”๋กœ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์ด ํ• ๋‹น๋˜๊ณ  ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์— ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณต์‚ฌ๋œ๋‹ค.

๋””์Šคํฌ์— ์žˆ๋Š” ํŒŒ์ผ์— ๋Œ€ํ•œ ์œ ์ € ๊ฐ€์ƒ ํŽ˜์ด์ง€๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ€์ƒ ์ฃผ์†Œ ๊ณต๊ฐ„์— ํ• ๋‹นํ•ด์ฃผ๋Š” ๊ฒƒ์„ mmap์ด๋ผ ํ•˜๊ณ , ํŽ˜์ด์ง€์™€ ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์—ฐ๊ฒฐ๋œ ๊ฒฝ์šฐ ๊ทธ ์—ฐ๊ฒฐ์„ ๋Š์–ด์ฃผ๋Š” ๊ฒƒ์„ munmap์ด๋ผ ํ•œ๋‹ค.

๋งŒ์•ฝ file backed page๊ฐ€ memory unmapped๋˜๊ฑฐ๋‚˜ swap out ๋˜๋ฉด, ํ•ด๋‹น ๋ฉ”๋ชจ๋ฆฌ์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธด ๊ฒฝ์šฐ(dirty bit) ๊ทธ ๋ณ€ํ™”๋ฅผ ํŒŒ์ผ์— ์—…๋ฐ์ดํŠธํ•˜๊ณ  memory unmapped๋˜๊ฑฐ๋‚˜ swap out๋˜์–ด์•ผ ํ•œ๋‹ค.

mmap() ์‹œ์Šคํ…œ ์ฝœ์— ์˜ํ•ด ๋งคํ•‘๋œ ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ๋Š” ์Šคํƒ๊ณผ ํž™ ์‚ฌ์ด์˜ ๋ฏธํ• ๋‹น ๊ณต๊ฐ„(์Šคํƒ๋„ ์•„๋‹ˆ๊ณ  ํž™๋„ ์•„๋‹Œ)์— ๋งคํ•‘๋œ๋‹ค.


๊ตฌํ˜„

1. mmap, do_mmap ๊ตฌํ˜„

1-1. mmap ์„ ์–ธํ•˜๊ธฐ

  • include/userprog/syscall.h
/** Project 3-Memory Mapped Files */
#include "include/filesys/off_t.h";
#include "stddef.h";
void *mmap(void *addr, size_t length, int writable, int fd, off_t offset);
void munmap(void *addr);

1-2. syscall์— mmap ์ถ”๊ฐ€

  • userprog/syscall.c
/** Project 3-Memory Mapped FIles */
#ifdef VM
        case SYS_MMAP:
            f->R.rax = mmap(f->R.rdi, f->R.rsi, f->R.rdx, f->R.r10, f->R.r8);
            break;
#endif
/** Project 3-Memory Mapped FIles */
#ifdef VM
void 
*mmap(void *addr, size_t length, int writable, int fd, off_t offset) {
    if (!addr || pg_round_down(addr) != addr || is_kernel_vaddr(addr) || is_kernel_vaddr(addr + length))
        return NULL;

    if (offset != pg_round_down(offset) || offset % PGSIZE != 0)
        return NULL;

    if (spt_find_page(&thread_current()->spt, addr))
        return NULL;

    struct file *file = process_get_file(fd);

    if ((file >= STDIN && file <= STDERR) || file == NULL)
        return NULL;

    if (file_length(file) == 0 || (long)length <= 0)
        return NULL;

    return do_mmap(addr, length, writable, file, offset);
}

#endif

1-3. filesys_lock ์ถ”๊ฐ€

  • include/userprog/syscall.h
/** Project 3-Memory Mapped Files */
#include "include/filesys/off_t.h";
#include "stddef.h";
void *mmap(void *addr, size_t length, int writable, int fd, off_t offset);
void munmap(void *addr);
extern struct lock filesys_lock;

1-4. do_mmap ๊ตฌํ˜„

  • vm/file.c
/** Project 3-Memory Mapped FIles */
#include "threads/vaddr.h"
#include "userprog/syscall.c"
.
.
.
void *
do_mmap (void *addr, size_t length, int writable,
		struct file *file, off_t offset) {
			
	/** Project 3-Memory Mapped FIles */
	lock_acquire(&filesys_lock);
    struct file *mfile = file_reopen(file);
    void *ori_addr = addr;
    size_t read_bytes = (length > file_length(mfile)) ? file_length(mfile) : length;
    size_t zero_bytes = PGSIZE - read_bytes % PGSIZE;

    ASSERT((read_bytes + zero_bytes) % PGSIZE == 0);
    ASSERT(pg_ofs(addr) == 0);
    ASSERT(offset % PGSIZE == 0);

    struct vm_load_arg *aux;
    while (read_bytes > 0 || zero_bytes > 0) {
        size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
        size_t page_zero_bytes = PGSIZE - page_read_bytes;

        aux = (struct vm_load_arg *)malloc(sizeof(struct vm_load_arg));
        if (!aux)
            goto err;

        aux->file = mfile;
        aux->ofs = offset;
        aux->read_bytes = page_read_bytes;

        if (!vm_alloc_page_with_initializer(VM_FILE, addr, writable, lazy_load_segment, aux)) {
            goto err;
        }

        read_bytes -= page_read_bytes;
        zero_bytes -= page_zero_bytes;
        addr += PGSIZE;
        offset += page_read_bytes;
    }
	lock_release(&filesys_lock);
    return ori_addr;

err:
    free(aux);
    lock_release(&filesys_lock);
    return NULL;
}

2. munmap, do_munmap ๊ตฌํ˜„

2-1. munmap ์„ ์–ธํ•˜๊ธฐ

  • include/userprog/syscall.h
/** Project 3-Memory Mapped Files */
#include "include/filesys/off_t.h";
#include "stddef.h";
void *mmap(void *addr, size_t length, int writable, int fd, off_t offset);
void munmap(void *addr);

2-2. syscall์— munmap ์ถ”๊ฐ€

  • userprog/syscall.c
/** Project 3-Memory Mapped FIles */
#ifdef VM
        case SYS_MMAP:
            f->R.rax = mmap(f->R.rdi, f->R.rsi, f->R.rdx, f->R.r10, f->R.r8);
            break;
        case SYS_MUNMAP:
            munmap(f->R.rdi);
            break;
#endif
/** Project 3-Memory Mapped Files */
void munmap(void *addr) {
    do_munmap(addr);
}

2-3. lazy_load_segment ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

  • include/userprog/process.h
/** #Project 3: Memory Mapped Files */
bool lazy_load_segment(struct page *page, void *aux);
  • userprog/process.c
  • static ์‚ญ์ œํ•˜๊ธฐ
  • BEFORE
static bool
lazy_load_segment (struct page *page, void *aux) {
	/** Project 3-Anonymous Page */
    struct vm_load_arg *aux_p = aux;
    .
    .
    .
  • AFTER
bool
lazy_load_segment (struct page *page, void *aux) {
	/** Project 3-Anonymous Page */
    struct vm_load_arg *aux_p = aux;
    .
    .
    .
  • vm/file.c
/** Project 3-Memory Mapped FIles */
#include "threads/mmu.h"
#include "threads/vaddr.h"
#include "userprog/process.h"
#include "userprog/syscall.h"

2-4. do_munmap() ๊ตฌํ˜„

  • vm/file.c
void
do_munmap (void *addr) {
	/** Project 3-Memory Mapped FIles */
    struct thread *curr = thread_current();
    struct page *page;

    lock_acquire(&filesys_lock);
    while ((page = spt_find_page(&curr->spt, addr))) {
        if (page)
            destroy(page);

        addr += PGSIZE;
    }
    lock_release(&filesys_lock);
}

3. file_backed_initializer() ๊ตฌํ˜„

  • vm/file.c
bool
file_backed_initializer (struct page *page, enum vm_type type, void *kva) {
	/* Set up the handler */
	page->operations = &file_ops;

	struct file_page *file_page = &page->file;

	/** Project 3-Memory Mapped Files */
    struct vm_load_arg *aux = (struct vm_load_arg *)page->uninit.aux;
    file_page->file = aux->file;
    file_page->offset = aux->ofs;
    file_page->page_read_bytes = aux->read_bytes;

    return true;
}

4. file_backed_destroy() ๊ตฌํ˜„

  • vm/file.c
static void
file_backed_destroy (struct page *page) {
	struct file_page *file_page UNUSED = &page->file;

	/** Project 3-Memory Mapped Files */
    if (pml4_is_dirty(thread_current()->pml4, page->va)) {
        file_write_at(file_page->file, page->va, file_page->page_read_bytes, file_page->offset);
        pml4_set_dirty(thread_current()->pml4, page->va, false);
    }

    if (page->frame) {
        list_remove(&page->frame->frame_elem);
        page->frame->page = NULL;
        page->frame = NULL;
        free(page->frame);
    }

    pml4_clear_page(thread_current()->pml4, page->va);
}

5. spt_remove_page() ์ˆ˜์ •

  • vm/vm.c
void
spt_remove_page (struct supplemental_page_table *spt, struct page *page) {
	/** Project 3-Memory Mapped Files */
	hash_delete(&thread_current()->spt.spt_hash, &page->hash_elem);
	vm_dealloc_page (page);
	return true;
}

6. supplemental_page_table_copy() ์ˆ˜์ •

  • vm/vm.c
  • TYPE ๊ด€๋ จ ์กฐ๊ฑด ์ถ”๊ฐ€
bool
supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED,
		struct supplemental_page_table *src UNUSED) {
	
	/** Project 3-Memory Mapped Files */
 	struct hash_iterator iter;
    hash_first(&iter, &src->spt_hash);
    while (hash_next(&iter)) {
        struct page *src_page = hash_entry(hash_cur(&iter), struct page, hash_elem);
        enum vm_type type = src_page->operations->type;
        void *upage = src_page->va;
        bool writable = src_page->writable;

        if (type == VM_UNINIT) {
            void *aux = src_page->uninit.aux;
            vm_alloc_page_with_initializer(page_get_type(src_page), upage, writable, src_page->uninit.init, aux);
        }

        else if (type == VM_FILE) {
            struct vm_load_arg *aux = malloc(sizeof(struct vm_load_arg));
            aux->file = src_page->file.file;
            aux->ofs = src_page->file.offset;
            aux->read_bytes = src_page->file.page_read_bytes;

            if (!vm_alloc_page_with_initializer(type, upage, writable, NULL, aux))
                return false;

            struct page *dst_page = spt_find_page(dst, upage);
            file_backed_initializer(dst_page, type, NULL);
            dst_page->frame = src_page->frame;
            pml4_set_page(thread_current()->pml4, dst_page->va, src_page->frame->kva, src_page->writable);
        }

        else {                                          
            if (!vm_alloc_page(type, upage, writable)) 
                return false;

            if (!vm_claim_page(upage))  
                return false;

            struct page *dst_page = spt_find_page(dst, upage); 
            memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
        }
    }

    return true;
}

7. page_fault ์กฐ๊ฑด ์ˆ˜์ •

  • userprog/exception.c
  • BEFORE
	if ((!not_present && write) || (fault_addr < 0x400000 ))
	{
		exit(-1);
	}
  • AFTER
	if ((!not_present && write) || (fault_addr < 0x400000 ))
	{
		exit(-1);
	}

์—ฌ๊ธฐ๊นŒ์ง€์˜ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

pass tests/userprog/args-none
pass tests/userprog/args-single
pass tests/userprog/args-multiple
pass tests/userprog/args-many
pass tests/userprog/args-dbl-space
pass tests/userprog/halt
pass tests/userprog/exit
pass tests/userprog/create-normal
pass tests/userprog/create-empty
pass tests/userprog/create-null
pass tests/userprog/create-bad-ptr
pass tests/userprog/create-long
pass tests/userprog/create-exists
pass tests/userprog/create-bound
pass tests/userprog/open-normal
pass tests/userprog/open-missing
pass tests/userprog/open-boundary
pass tests/userprog/open-empty
pass tests/userprog/open-null
pass tests/userprog/open-bad-ptr
pass tests/userprog/open-twice
pass tests/userprog/close-normal
pass tests/userprog/close-twice
pass tests/userprog/close-bad-fd
pass tests/userprog/read-normal
pass tests/userprog/read-bad-ptr
pass tests/userprog/read-boundary
pass tests/userprog/read-zero
pass tests/userprog/read-stdout
pass tests/userprog/read-bad-fd
pass tests/userprog/write-normal
pass tests/userprog/write-bad-ptr
pass tests/userprog/write-boundary
pass tests/userprog/write-zero
pass tests/userprog/write-stdin
pass tests/userprog/write-bad-fd
pass tests/userprog/fork-once
pass tests/userprog/fork-multiple
pass tests/userprog/fork-recursive
pass tests/userprog/fork-read
pass tests/userprog/fork-close
pass tests/userprog/fork-boundary
pass tests/userprog/exec-once
pass tests/userprog/exec-arg
pass tests/userprog/exec-boundary
pass tests/userprog/exec-missing
pass tests/userprog/exec-bad-ptr
pass tests/userprog/exec-read
pass tests/userprog/wait-simple
pass tests/userprog/wait-twice
pass tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
pass tests/userprog/multi-recurse
pass tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
pass tests/userprog/rox-child
pass tests/userprog/rox-multichild
pass tests/userprog/bad-read
pass tests/userprog/bad-write
pass tests/userprog/bad-read2
pass tests/userprog/bad-write2
pass tests/userprog/bad-jump
pass tests/userprog/bad-jump2
pass tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
pass tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
pass tests/vm/pt-write-code
pass tests/vm/pt-write-code2
pass tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
pass tests/vm/page-parallel
pass tests/vm/page-merge-seq
pass tests/vm/page-merge-par
FAIL tests/vm/page-merge-stk
FAIL tests/vm/page-merge-mm
pass tests/vm/page-shuffle
pass tests/vm/mmap-read
pass tests/vm/mmap-close
pass tests/vm/mmap-unmap
pass tests/vm/mmap-overlap
pass tests/vm/mmap-twice
pass tests/vm/mmap-write
pass tests/vm/mmap-ro
pass tests/vm/mmap-exit
pass tests/vm/mmap-shuffle
pass tests/vm/mmap-bad-fd
pass tests/vm/mmap-clean
pass tests/vm/mmap-inherit
pass tests/vm/mmap-misalign
pass tests/vm/mmap-null
pass tests/vm/mmap-over-code
pass tests/vm/mmap-over-data
pass tests/vm/mmap-over-stk
pass tests/vm/mmap-remove
pass tests/vm/mmap-zero
pass tests/vm/mmap-bad-fd2
pass tests/vm/mmap-bad-fd3
pass tests/vm/mmap-zero-len
pass tests/vm/mmap-off
pass tests/vm/mmap-bad-off
pass tests/vm/mmap-kernel
pass tests/vm/lazy-file
pass tests/vm/lazy-anon
FAIL tests/vm/swap-file
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
FAIL tests/vm/swap-fork
pass tests/filesys/base/lg-create
pass tests/filesys/base/lg-full
pass tests/filesys/base/lg-random
pass tests/filesys/base/lg-seq-block
pass tests/filesys/base/lg-seq-random
pass tests/filesys/base/sm-create
pass tests/filesys/base/sm-full
pass tests/filesys/base/sm-random
pass tests/filesys/base/sm-seq-block
pass tests/filesys/base/sm-seq-random
pass tests/filesys/base/syn-read
pass tests/filesys/base/syn-remove
pass tests/filesys/base/syn-write
pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
pass tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
pass tests/threads/priority-change
pass tests/threads/priority-donate-one
pass tests/threads/priority-donate-multiple
pass tests/threads/priority-donate-multiple2
pass tests/threads/priority-donate-nest
pass tests/threads/priority-donate-sema
pass tests/threads/priority-donate-lower
pass tests/threads/priority-fifo
pass tests/threads/priority-preempt
pass tests/threads/priority-sema
pass tests/threads/priority-condvar
pass tests/threads/priority-donate-chain
FAIL tests/vm/cow/cow-simple
7 of 141 tests failed.
  • tests/vm/page-merge-seq
  • tests/vm/page-merge-par
  • tests/vm/page-merge-stk
  • tests/vm/page-merge-mm

๐Ÿ˜น page-merge ๊ด€๋ จ ํ…Œ์ŠคํŠธ๋“ค์ด ์ „๋ถ€ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์ด์œ ๊ฐ€ ๋ญ˜๊นŒ...

open์ด ์‹คํŒจํ–ˆ๋‹ค๊ณ  ๋œฌ๋‹ค...
ํŒ€์›์—๊ฒŒ ๋ฌผ์–ด๋ณด๋‹ˆ ์†๋„๊ฐ€ ๋น ๋ฅธ๊ฑฐ๋ผ๊ณ  ํ•œ๋‹ค..(?)
๊ทธ๋ฆฌ๊ณ  fdt๋ฅผ linked_list๋กœ ๊ตฌํ˜„ํ•œ ํŒ€์€ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.
ํŒ€์› ๋ง๋กœ๋Š” linked_list๊ฐ€ ๊ฒ€์ƒ‰ ์†๋„๊ฐ€ ๋Š๋ ค์„œ ์†๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ํ•œ๋‹ค.

ํ•ด๊ฒฐํ•˜์ž!!!!!!!!!


page-merge FAIL ํ•ด๊ฒฐํ•˜๊ธฐ

1. lock์„ ์ถ”๊ฐ€ํ•˜์ž!

1-1. syscall lock

  • userprog/syscall.c
  • create, remove, open์— lock์„ ์ถ”๊ฐ€ํ•ด์คฌ๋‹ค.
bool 
create(const char *file, unsigned initial_size) 
{
    check_address(file);

    lock_acquire(&filesys_lock);
    bool success = filesys_create(file, initial_size);
    lock_release(&filesys_lock);

    return success;
}

bool 
remove(const char *file) 
{
    check_address(file);

    lock_acquire(&filesys_lock);
    bool success = filesys_remove(file);
    lock_release(&filesys_lock);

    return success;
}

int 
open(const char *file) 
{
    check_address(file);

    lock_acquire(&filesys_lock);
    struct file *newfile = filesys_open(file);

    if (newfile == NULL)
        goto err;

    int fd = process_add_file(newfile);

    if (fd == -1)
        file_close(newfile);

    lock_release(&filesys_lock);
    return fd;
err:
    lock_release(&filesys_lock);
    return -1;
}

1-2. load lock

  • userprog/process.c
  • lock ์ถ”๊ฐ€๋ฅผ ์œ„ํ•ด syscall.h include ํ•˜๊ธฐ
/** Project 3-Memory Mapped FIles */
#include "userprog/syscall.h"
  • load ํ•จ์ˆ˜์— lock์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
static bool
load (const char *file_name, struct intr_frame *if_) {
	struct thread *t = thread_current();
    struct ELF ehdr;
    struct file *file = NULL;
    off_t file_ofs;
    bool success = false;
    int i;

    /* Allocate and activate page directory. */
    t->pml4 = pml4_create();
    if (t->pml4 == NULL)
        goto done;
    process_activate(thread_current());

    /* Open executable file. */
    lock_acquire(&filesys_lock); /** Project 3-Memory Mapped FIles */
    file = filesys_open(file_name);
    if (file == NULL) {
        printf("load: %s: open failed\n", file_name);
        goto done;
    }

    /** project2-System Call - ํŒŒ์ผ ์‹คํ–‰ ๋ช…์‹œ ๋ฐ ์ ‘๊ทผ ๊ธˆ์ง€ ์„ค์ •  */
    t->runn_file = file;
    file_deny_write(file); /** Project 2: Denying Writes to Executables */

    /* Read and verify executable header. */
    if (file_read(file, &ehdr, sizeof ehdr) != sizeof ehdr || memcmp(ehdr.e_ident, "\177ELF\2\1\1", 7) || ehdr.e_type != 2 || ehdr.e_machine != 0x3E  // amd64
        || ehdr.e_version != 1 || ehdr.e_phentsize != sizeof(struct Phdr) || ehdr.e_phnum > 1024) {
        printf("load: %s: error loading executable\n", file_name);
        goto done;
    }

    /* Read program headers. */
    file_ofs = ehdr.e_phoff;
    for (i = 0; i < ehdr.e_phnum; i++) {
        struct Phdr phdr;

        if (file_ofs < 0 || file_ofs > file_length(file))
            goto done;
        file_seek(file, file_ofs);

        if (file_read(file, &phdr, sizeof phdr) != sizeof phdr)
            goto done;
        file_ofs += sizeof phdr;
        switch (phdr.p_type) {
            case PT_NULL:
            case PT_NOTE:
            case PT_PHDR:
            case PT_STACK:
            default:
                /* Ignore this segment. */
                break;
            case PT_DYNAMIC:
            case PT_INTERP:
            case PT_SHLIB:
                goto done;
            case PT_LOAD:
                if (validate_segment(&phdr, file)) {
                    bool writable = (phdr.p_flags & PF_W) != 0;
                    uint64_t file_page = phdr.p_offset & ~PGMASK;
                    uint64_t mem_page = phdr.p_vaddr & ~PGMASK;
                    uint64_t page_offset = phdr.p_vaddr & PGMASK;
                    uint32_t read_bytes, zero_bytes;
                    if (phdr.p_filesz > 0) {
                        /* Normal segment.
                         * Read initial part from disk and zero the rest. */
                        read_bytes = page_offset + phdr.p_filesz;
                        zero_bytes = (ROUND_UP(page_offset + phdr.p_memsz, PGSIZE) - read_bytes);
                    } else {
                        /* Entirely zero.
                         * Don't read anything from disk. */
                        read_bytes = 0;
                        zero_bytes = ROUND_UP(page_offset + phdr.p_memsz, PGSIZE);
                    }
                    if (!load_segment(file, file_page, (void *)mem_page, read_bytes, zero_bytes, writable))
                        goto done;
                } else
                    goto done;
                break;
        }
    }

    /* Set up stack. */
    if (!setup_stack(if_))
        goto done;

    /* Start address. */
    if_->rip = ehdr.e_entry;

    success = true;

done:
    /* We arrive here whether the load is successful or not. */
    // file_close(file);
    lock_release(&filesys_lock); /** Project 3-Memory Mapped FIles */
    return success;
}

2. check_valid_buffer()๋ฅผ ๊ตฌํ˜„ํ•˜์ž!

  • include/userprog/syscall.h
void check_valid_buffer(void *buffer, size_t size, bool writable);
  • userprog/syscall.c
/** Project 3-Memory Mapped Files ๋ฒ„ํผ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ */
void check_valid_buffer(void *buffer, size_t size, bool writable) {
    for (size_t i = 0; i < size; i += 8) {
        /* buffer๊ฐ€ spt์— ์กด์žฌํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ */
        struct page *page = check_address(buffer + i);

        if (!page || (writable && !(page->writable)))
            exit(-1);
    }
}

์–ด๋–ค๋•Œ์—๋Š” ++ ์ฆ๊ฐ์œผ๋กœ ํ•ด์•ผ ํ†ต๊ณผํ•˜๊ณ , ์–ด๋–ค๋•Œ์—๋Š” +=8 ์ฆ๊ฐ์œผ๋กœ ํ•ด์•ผ ํ†ต๊ณผ๊ฐ€ ๋๋‹ค.
ํ•˜์ง€๋งŒ ์ง€๊ธˆ์€ +=8๋กœ ๊ณ„์† ํ†ต๊ณผ๋˜๋Š” ์ถ”์„ธ...
์ด์œ ๋Š” ๋ชจ๋ฅด๊ฒ ๋”ฐ.. ใ…œใ…œ
open ๋ฌธ์ œ์™€ TIMEOUT ๋ฌธ์ œ๊ฐ€ ๋ฐ˜๋ณต๋œ๋‹ค๋ฉด ์ด ์ฆ๊ฐ์„ ์ค„์ด๊ฑฐ๋‚˜ ๋Š˜๋ ค์„œ ํ•ด๊ฒฐํ•ด๋ณด์ž ใ…œใ…œ

  • read, write์— ์ถ”๊ฐ€
int 
read(int fd, void *buffer, unsigned length) 
{
#ifdef VM
    check_valid_buffer(buffer, length, true);
#endif
...

}

int 
write(int fd, const void *buffer, unsigned length) 
{
#ifdef VM
    check_valid_buffer(buffer, length, false);
#endif
...
}

์—ฌ๊ธฐ๊นŒ์ง€ ํ–ˆ๋Š”๋ฐ๋„ fork์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋–ด์—ˆ๋‹ค...
project1์—์„œ ๊ตฌํ˜„ํ•œ donate_prorty() ๋ฌธ์ œ์˜€๋‹ค ใ…œใ…œ

3. fork ์—๋Ÿฌ ํ•ด๊ฒฐ

  • threads/thread.c
if (t == NULL)
		break;

์กฐ๊ฑด์„ ์ถ”๊ฐ€ํ•ด์ฃผ์ž

void 
donate_priority() 
{
    struct thread *t = thread_current();
    int priority = t->priority;

    for (int depth = 0; depth < 8; depth++) 
	{
        if (t->wait_lock == NULL)
            break;
        t = t->wait_lock->holder;
		/** Project 3-Memory Mapped Files */
		if (t == NULL)
			break;
        t->priority = priority;
    }
}

์ตœ์ข… ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

pass tests/userprog/args-none
pass tests/userprog/args-single
pass tests/userprog/args-multiple
pass tests/userprog/args-many
pass tests/userprog/args-dbl-space
pass tests/userprog/halt
pass tests/userprog/exit
pass tests/userprog/create-normal
pass tests/userprog/create-empty
pass tests/userprog/create-null
pass tests/userprog/create-bad-ptr
pass tests/userprog/create-long
pass tests/userprog/create-exists
pass tests/userprog/create-bound
pass tests/userprog/open-normal
pass tests/userprog/open-missing
pass tests/userprog/open-boundary
pass tests/userprog/open-empty
pass tests/userprog/open-null
pass tests/userprog/open-bad-ptr
pass tests/userprog/open-twice
pass tests/userprog/close-normal
pass tests/userprog/close-twice
pass tests/userprog/close-bad-fd
pass tests/userprog/read-normal
pass tests/userprog/read-bad-ptr
pass tests/userprog/read-boundary
pass tests/userprog/read-zero
pass tests/userprog/read-stdout
pass tests/userprog/read-bad-fd
pass tests/userprog/write-normal
pass tests/userprog/write-bad-ptr
pass tests/userprog/write-boundary
pass tests/userprog/write-zero
pass tests/userprog/write-stdin
pass tests/userprog/write-bad-fd
pass tests/userprog/fork-once
pass tests/userprog/fork-multiple
pass tests/userprog/fork-recursive
pass tests/userprog/fork-read
pass tests/userprog/fork-close
pass tests/userprog/fork-boundary
pass tests/userprog/exec-once
pass tests/userprog/exec-arg
pass tests/userprog/exec-boundary
pass tests/userprog/exec-missing
pass tests/userprog/exec-bad-ptr
pass tests/userprog/exec-read
pass tests/userprog/wait-simple
pass tests/userprog/wait-twice
pass tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
pass tests/userprog/multi-recurse
pass tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
pass tests/userprog/rox-child
pass tests/userprog/rox-multichild
pass tests/userprog/bad-read
pass tests/userprog/bad-write
pass tests/userprog/bad-read2
pass tests/userprog/bad-write2
pass tests/userprog/bad-jump
pass tests/userprog/bad-jump2
pass tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
pass tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
pass tests/vm/pt-write-code
pass tests/vm/pt-write-code2
pass tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
pass tests/vm/page-parallel
pass tests/vm/page-merge-seq
pass tests/vm/page-merge-par
pass tests/vm/page-merge-stk
pass tests/vm/page-merge-mm
pass tests/vm/page-shuffle
pass tests/vm/mmap-read
pass tests/vm/mmap-close
pass tests/vm/mmap-unmap
pass tests/vm/mmap-overlap
pass tests/vm/mmap-twice
pass tests/vm/mmap-write
pass tests/vm/mmap-ro
pass tests/vm/mmap-exit
pass tests/vm/mmap-shuffle
pass tests/vm/mmap-bad-fd
pass tests/vm/mmap-clean
pass tests/vm/mmap-inherit
pass tests/vm/mmap-misalign
pass tests/vm/mmap-null
pass tests/vm/mmap-over-code
pass tests/vm/mmap-over-data
pass tests/vm/mmap-over-stk
pass tests/vm/mmap-remove
pass tests/vm/mmap-zero
pass tests/vm/mmap-bad-fd2
pass tests/vm/mmap-bad-fd3
pass tests/vm/mmap-zero-len
pass tests/vm/mmap-off
pass tests/vm/mmap-bad-off
pass tests/vm/mmap-kernel
pass tests/vm/lazy-file
pass tests/vm/lazy-anon
FAIL tests/vm/swap-file
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
FAIL tests/vm/swap-fork
pass tests/filesys/base/lg-create
pass tests/filesys/base/lg-full
pass tests/filesys/base/lg-random
pass tests/filesys/base/lg-seq-block
pass tests/filesys/base/lg-seq-random
pass tests/filesys/base/sm-create
pass tests/filesys/base/sm-full
pass tests/filesys/base/sm-random
pass tests/filesys/base/sm-seq-block
pass tests/filesys/base/sm-seq-random
pass tests/filesys/base/syn-read
pass tests/filesys/base/syn-remove
pass tests/filesys/base/syn-write
pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
pass tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
pass tests/threads/priority-change
pass tests/threads/priority-donate-one
pass tests/threads/priority-donate-multiple
pass tests/threads/priority-donate-multiple2
pass tests/threads/priority-donate-nest
pass tests/threads/priority-donate-sema
pass tests/threads/priority-donate-lower
pass tests/threads/priority-fifo
pass tests/threads/priority-preempt
pass tests/threads/priority-sema
pass tests/threads/priority-condvar
pass tests/threads/priority-donate-chain
FAIL tests/vm/cow/cow-simple
5 of 141 tests failed.

swap in/out๊ณผ cow test ์ œ์™ธํ•˜๊ณ  ์ „๋ถ€ PASS๋‹ค!!!!๐Ÿ˜‡

profile
Sunny Day!

0๊ฐœ์˜ ๋Œ“๊ธ€