Sector = 512bytes -> 8개의 섹터가 하나의 페이지를 이룬다.
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
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
FAIL 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
pass tests/vm/swap-fork
FAIL tests/vm/cow/cow-simple
6 of 141 tests failed.
Swap 구현은 우선 했는데, 아직 빠진 부분이 있는지 실패하는 부분들이 있다
그리고 supplemental page table copy에서의 허점을 발견해서 고쳐야 한다.
👉🏻 처음에는 naive 하게 uninit은 uninit 상태로, 그 외 모든 페이지는 그냥 복제를 해주도록 코드를 짰는데, 그러면 page의 멤버들이 정상적으로 값이 세팅되지 않을 것이라는 문제가 있었다. 이 문제를 해결하기 위해서 file-backed는 file-backed init 프로세스에 맞춰 다시 initiate, anonymous는 그 페이지에 맞게, 그리고 swap out 된 페이지는 다시 메모리로 로드하는 방식으로 구현해야한다.
👉🏻 Swap out 된 페이지의 경우 swap disk에서 복제해서 다시 swap disk로 넣어야 하나 하고 생각할 수도 있는데, 메모리에 해당 페이지를 올릴 때 메모리가 부족한 경우 알아서 다른 프로세스의 페이지가 frame_table의 순서에 맞춰서 evict 될 것이기 때문에 해당 프로세스는 모든 페이지를 메모리에 바로 올리면 된다.
Changes :
위 사항까지 고치고 나니 swap file 과 swap anon 테스트는 통과하였다!
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
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
FAIL tests/vm/mmap-exit
pass tests/vm/mmap-shuffle
pass tests/vm/mmap-bad-fd
pass tests/vm/mmap-clean
FAIL 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
FAIL tests/vm/swap-fork
FAIL tests/vm/cow/cow-simple
5 of 141 tests failed.
Changes :
Feat :
위와 같은 변화를 줘 본 결과 하나의 테스트케이스를 더 맞긴 했는데, 이전에 맞던게 이번에는 틀리고 있다...
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
FAIL 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
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
pass tests/vm/swap-fork
FAIL tests/vm/cow/cow-simple
4 of 141 tests failed.
mmap-inherit.result
Kernel panic in run: PANIC at ../../filesys/inode.c:304 in inode_allow_write(): assertion `inode->deny_write_cnt > 0' failed.
Call stack: 0x8004217f8f 0x80042207be 0x800421f615 0x800421f3c2 0x8004222a41 0x8004221b1b 0x8004222072 0x800421a55d 0x800421a5e0 0x8004221f80 0x800421c003 0x800421bdae 0x8004207278 0x800421d6e0 0x800421d35f 0x800421d1bd 0x400e5c
Translation of call stack:
0x0000008004217f8f: debug_panic (lib/kernel/debug.c:32)
0x00000080042207be: inode_allow_write (filesys/inode.c:305)
0x000000800421f615: file_allow_write (filesys/file.c:137)
0x000000800421f3c2: file_close (filesys/file.c:56)
0x0000008004222a41: file_backed_destroy (vm/file.c:100)
0x0000008004221b1b: vm_dealloc_page (vm/vm.c:253)
0x0000008004222072: spt_destroy_func (vm/vm.c:365)
0x000000800421a55d: hash_clear (lib/kernel/hash.c:58)
0x000000800421a5e0: hash_destroy (lib/kernel/hash.c:84)
0x0000008004221f80: supplemental_page_table_kill (vm/vm.c:348)
0x000000800421c003: process_cleanup (userprog/process.c:424)
0x000000800421bdae: process_exit (userprog/process.c:357)
0x0000008004207278: thread_exit (threads/thread.c:339)
0x000000800421d6e0: fork (userprog/syscall.c:206)
0x000000800421d35f: syscall_handler (userprog/syscall.c:100)
0x000000800421d1bd: no_sti (userprog/syscall-entry.o:?)
0x0000000000400e5c: (unknown)
deny_write 한 개수가 0이상이어야 close하면서 해당 개수를 줄여줄 수 있는데, 0 이상이 아니기에 발생하는 assertion fail이라고 이해하였다. file_reopen을 잘못한 건가 싶었는데.. 꼭 그렇지만도 않은 것 같다.. 아니면 과하게 close를 한건가..? 어떨 때 해당 count가 수정되는지 한번 알아봐야할 것 같다.
해당 변수는 deny_write을 호출할 때 +가 되고, deny_write은 load에서 running_file에 대해서 사용하며, file_duplicate에서도 부른다. file_duplicate는 do_fork에서 fdTable을 복제할 때 사용된다. (결국 supplemental_page_table_copy를 수정한 후 해결이 되었다.)
위 문제를 보다 보니까 evict frame을 할 때 evict 당하는 frame은 현재 프로세스의 프레임이 아닌 다른 프로세스의 프레임일 수 있기 때문에 전체적으로 thread_current()
의 pml4를 사용하면 안될 것이라는 걸 깨달았다. 따라서, page 별로 그 페이지가 속해있는 thread를 연결해주는 방식을 적용해보았다.
get_victim
에서 pml4_accessed
를 확인할 때 swap_out
에서 pml4_dirty
를 확인할 때 pml4_clear_page
할 때 적용해도 결과는 다르지 않았고, all pass가 뜨는 팀원의 코드도 해당 부분이 반영되어있지 않아서... 정상 작동이 되지 않을텐데 왜 pass가 뜨는지 의문이다....
👉🏻 팀원의 경우 위에서 언급한 supplemental_page_table_copy의 허점을 고쳐서 구현하는 작업을 먼저 하고 있었는데, 이 부분을 고치면 swap disk가 꽉 차서 터지는 경우가 발생했었다. 그런데 알고보니 결국 위에서 말한 eviction 프로세스에서의 코드 문제 때문이었던 것이다! frame evicton에서 thread_current() 함수를 사용하기 때문에, evict 하려는 프레임이 속해있는 프로세스에서 프레임을 evict 한 것이 아니라, 동일한 가상주소를 가진 현재 프로세스의 프레임을 evict 하고 있었던 것이다.
정말 신기한 것은 spt copy와 evict 시 thread_current를 사용하는 부분을 고치기 이전에도 All pass가 떴었다는 소름 돋는 사실... (카이스트 교수님들은 히든 테스트 케이스를 가지고 있다는 소문이 있던데.. 이런 부분들은 학생들이 스스로 생각해서 구현하도록 하려고 일부러 테스트 케이스를 간단하게 내신게 아닐까 하는 생각이 든다. 😅 )
그래서 팀원의 copy 함수를 내거에 적용한 결과 inherit 도 해결되고 swap-anon, file, iter도 해결이 되었다.
그런데 아직 swap-fork 가 남았다...
너... 뭐가 문젠데...!?
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
FAIL tests/vm/swap-fork
FAIL tests/vm/cow/cow-simple
2 of 141 tests failed.
그런데.. swap-fork output을 확인해보니 아무것도 없는 상태로 killed......? 이거 왜이래...?
정말 당황스러웠지만 결국 AWS의 내 ubuntu 서버가 계속 버거워했던 것 같아서 EC2 인스턴스를 재부팅 해주었다.
그랬더니...됐다...!
드디어 ALL PASS !
pass tests/threads/priority-donate-chain
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
All 140 tests passed.
이렇게 행복할 수 없다 ㅠㅠ
3일을 더 써서 드디어 Virtual Memory를 끝냈다.
이제 File System 하자!!!