๐ฉ๐ปโ๐ป GITHUB ๋ ํฌ์งํ ๋ฆฌ
๐ฉ๐ปโ๐ป GITHUB Swap In / Out ์ด์
Memory swapping์ physical memory ์ฌ์ฉ์ ๊ทน๋ํํ๊ธฐ ์ํ memory ํ์ ๊ธฐ๋ฒ์ด๋ค. main memory์ frame์ด ํ ๋น๋๋ฉด system์ user program์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ฒญ์ ๋ ์ด์ ์ฒ๋ฆฌํ ์ ์๋ค. ํ ๊ฐ์ง ํด๊ฒฐ์ฑ ์ ์ต๊ทผ์ ์ฌ์ฉ๋์ง ์๋ memory frame์ disk๋ก ๊ต์ฒดํ๋ ๊ฒ์ด๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ผ๋ถ memory resource๊ฐ ํ๋ณด๋์ด ๋ค๋ฅธ ์์ฉํ๋ก๊ทธ๋จ์์ ์ฌ์ฉ ๊ฐ๋ฅํด์ง๋ค.
๊ฐ์ ์ฃผ์ ์์ VPN์ Present Bit์ ๋์ด ํด๋น ํ์ด์ง๊ฐ ๋์คํฌ๋ก ์ค์๋์๋์ง๋ฅผ ๋ํ๋ธ๋ค.
swapping์ OS ์ ์ํด ์คํ๋๋ค. system์์ memory๊ฐ ๋ถ์กฑํ๋ฐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ฒญ์ ๋ฐ์ผ๋ฉด ๊ตํํ (evict) page๋ฅผ ๊ณ ๋ฅธ๋ค. ๊ทธ ๋ค์ ๋ฉ๋ชจ๋ฆฌ frame์ ์ ํํ ์ํ๊ฐ disk์ ๋ณต์ฌ๋๋ค. ํ๋ก์ธ์ค๊ฐ swap out๋ page์ ์ก์ธ์คํ๋ ค๊ณ ํ๋ฉด OS๋ ์ ํํ ๋ด์ฉ์ memory์ ๋ค์ ๊ฐ์ ธ์์ page๋ฅผ ๋ณต๊ตฌํ๋ค.
โ๏ธ ์๋ฃ๊ตฌ์กฐ, lock, ํค๋ํ์ผ ์ ์ธํ๊ธฐ!
/** Project 3-Swap In/Out */
#include <bitmap.h>
#include "threads/vaddr.h"
#define SECTOR_PER_PAGE (PGSIZE / DISK_SECTOR_SIZE)
static struct bitmap *swap_bitmap;
static struct lock swap_lock;
๐ก SECTORS_PER_PAGE
ํ ํ์ด์ง์ ๋ค์ด๊ฐ ์ ์๋ ๋์คํฌ ์นํฐ์ ๊ฐ์๋ฅผ ์๋ฏธํ๋ค.PGSIZE == 1<<12 == 4kb
์ด๊ณDISK_SECTOR_SIZE == 512byte
์ด๋ค.
swap_size
๋ ์ค์ ๋์คํฌ ์์์ ๋ง๋ค ์ ์๋ ์ค์ ์ฌ๋กฏ์ ๊ฐ์๋ฅผ ์๋ฏธํ๋ค.void
vm_anon_init (void) {
/** Project 3-Swap In/Out */
swap_disk = disk_get(1, 1);
swap_bitmap = bitmap_create(disk_size(swap_disk) / SECTOR_PER_PAGE);
lock_init(&swap_lock);
}
struct anon_page {
/** Project 3-Swap In/Out */
size_t page_no;
};
bool
anon_initializer (struct page *page, enum vm_type type, void *kva) {
/** Project 3-Swap In/Out */
struct uninit_page *uninit = &page->uninit;
memset(uninit, 0, sizeof(struct uninit_page));
page->operations = &anon_ops;
struct anon_page *anon_page = &page->anon;
anon_page->page_no = BITMAP_ERROR;
return true;
}
static bool
anon_swap_out (struct page *page) {
struct anon_page *anon_page = &page->anon;
/** Project 3-Swap In/Out */
lock_acquire(&swap_lock);
size_t page_no = bitmap_scan_and_flip(swap_bitmap, 0, 1, false);
if (page_no == BITMAP_ERROR){
lock_release(&swap_lock);
return false;
}
for (size_t i = 0; i < SECTOR_PER_PAGE; i++)
disk_write(swap_disk, (page_no * SECTOR_PER_PAGE) + i, page->va + (i * DISK_SECTOR_SIZE));
anon_page->page_no = page_no;
page->frame->page = NULL;
page->frame = NULL;
pml4_clear_page(thread_current()->pml4, page->va);
lock_release(&swap_lock);
}
static bool
anon_swap_in (struct page *page, void *kva) {
struct anon_page *anon_page = &page->anon;
/** Project 3-Swap In/Out */
lock_acquire(&swap_lock);
if (anon_page->page_no == BITMAP_ERROR){
lock_release(&swap_lock);
return false;
}
if (!bitmap_test(swap_bitmap, anon_page->page_no)){
lock_release(&swap_lock);
return false;
}
for (size_t i = 0; i < SECTOR_PER_PAGE; i++)
disk_read(swap_disk, (anon_page->page_no * SECTOR_PER_PAGE) + i, kva + (i * DISK_SECTOR_SIZE));
bitmap_set(swap_bitmap, anon_page->page_no, false);
lock_release(&swap_lock);
anon_page->page_no = BITMAP_ERROR;
return true;
}
static void
anon_destroy (struct page *page) {
struct anon_page *anon_page = &page->anon;
/** Project 3-Swap In/Out */
if (anon_page->page_no != BITMAP_ERROR)
bitmap_reset(swap_bitmap, anon_page->page_no);
if (page->frame) {
lock_acquire(&swap_lock);
list_remove(&page->frame->frame_elem);
lock_release(&swap_lock);
page->frame->page = NULL;
free(page->frame);
page->frame = NULL;
}
}
static bool
file_backed_swap_out (struct page *page) {
struct file_page *file_page UNUSED = &page->file;
/** Project 3-Swap In/Out */
struct frame *frame = page->frame;
if (pml4_is_dirty(thread_current()->pml4, page->va))
{
file_write_at(file_page->file, page->frame->kva, file_page->page_read_bytes, file_page->offset);
pml4_set_dirty(thread_current()->pml4, page->va, false);
}
page->frame->page = NULL;
page->frame = NULL;
pml4_clear_page(thread_current()->pml4, page->va);
return true;
}
static bool
file_backed_swap_in (struct page *page, void *kva) {
struct file_page *file_page UNUSED = &page->file;
/** Project 3-Swap In/Out */
int read = file_read_at(file_page->file, page->frame->kva, file_page->page_read_bytes, file_page->offset);
memset(page->frame->kva + read, 0, PGSIZE - read);
return true;
}
/** Project 3-Swap In/Out */
struct lock frame_lock;
void
vm_init (void) {
vm_anon_init ();
vm_file_init ();
#ifdef EFILESYS /* For project 4 */
pagecache_init ();
#endif
register_inspect_intr ();
/* DO NOT MODIFY UPPER LINES. */
/** Project 3-Memory Management */
list_init(&frame_table);
/** Project 3-Swap In/Out */
lock_init(&frame_lock);
}
/** Project 3-Swap In/Out */
struct lock frame_lock;
struct list_elem *next = NULL;
static struct frame *
vm_get_victim (void) {
struct frame *victim = NULL;
/** Project 3-Swap In/Out */
lock_acquire(&frame_lock);
for (next = list_begin(&frame_table); next != list_end(&frame_table); next = list_next(next))
{
victim = list_entry(next, struct frame, frame_elem);
if (pml4_is_accessed(thread_current()->pml4, victim->page->va))
pml4_set_accessed(thread_current()->pml4, victim->page->va, false);
else{
lock_release(&frame_lock);
return victim;
}
}
lock_release(&frame_lock);
return victim;
}
static struct frame *
vm_evict_frame (void) {
/** Project 3-Swap In/Out */
struct frame *victim = vm_get_victim ();
if (victim->page)
swap_out(victim->page);
return victim;
}
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
pass tests/vm/swap-file
pass tests/vm/swap-anon
pass tests/vm/swap-iter
pass 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
1 of 141 tests failed.
ec2 ํ๊ฒฝ์์ swap-fork๊ฐ FAILํ์์ง๋ง, WSL ํ๊ฒฝ์์ passํ๋ ๊ฒ์ ํ์ธํจ.