미소를뿌리는감자의 코딩
[Pintos_project3 (21)] extra 본문
728x90
//vm/anon.c
static void
anon_destroy (struct page *page) {
struct anon_page *anon_page = &page->anon;
/* pseudo
* anon이 사용 중인 리소스 해제, page는 caller가 해제할 것이므로 신경 안써도 된다.
* anon이 사용 중인 frame, page를 해제*/
// 점거 중인 bitmap 삭제 --- 까먹었던 거 추가
if (anon_page->slot != BITMAP_ERROR)
bitmap_reset(swap_table, anon_page->slot);
if (page->frame) {
list_remove(&page->frame->frame_elem); // 리스트에서 해당 frame 제거
page->frame->page = NULL; // frame이 page를 가리키는 포인터 제거. NULL
free(page->frame); // 이후, frame을 free
page->frame = NULL; // page가 frame을 가리키는 포인터 제거. NULL
}
}
// threads/thread.c
/** #Project 1: Priority Donation 현재 쓰레드가 기다리고 있는 lock과 연결된 모든 쓰레드들을 순회하며
* 현재 쓰레드의 우선순위를 lock을 보유하고 있는 쓰레드에게 기부한다. */
void donate_priority() {
thread_t *t = thread_current();
int priority = t->priority;
for (int depth = 0; depth < 8; depth++) {
/* project 3: child가 먼저 삭제되면 holder가 NULL이 되는 경우.*/
if (t->wait_lock == NULL || t->wait_lock->holder==NULL)
break;
t = t->wait_lock->holder;
t->priority = priority;
}
}
test 결과
// vm/file.c
/* Swap out the page by writeback contents to the file. */
static bool
file_backed_swap_out (struct page *page) {
/* pseudo
* (dirty 유무 확인)
* (true) file에 변경사항 저장. dirty하지 않다고 명시
* (false) 바로 swap_out 진행. RAM에서 해당 frame 사용 중이지 않다고 명시.*/
struct file_page *file_page UNUSED = &page->file;
if (pml4_is_dirty(thread_current()->pml4, page->va)) { // dirty인지 확인. 더럽다면 file에 적어두고, dirty이지 않다고 명시
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);
}
//page와 frame 연관관계 끊기
page->frame->page = NULL;
page->frame = NULL;
pml4_clear_page(thread_current()->pml4, page->va);
return true; // 이걸 잊었었다...
}
// vm/vm.c
void
spt_remove_page (struct supplemental_page_table *spt, struct page *page) {
hash_delete(&thread_current()->spt.spt_hash, &page->hash_elem); // *** extra
vm_dealloc_page (page);
return true;
}
/** #Project 2: System Call - 스레드 TID가 종료될 때까지 기다리고 종료 상태를 반환합니다.
* 커널에 의해 종료된 경우 (즉, 예외로 인해 종료된 경우) -1을 반환합니다. TID가 유효하지
* 않거나 호출 프로세스의 하위 프로세스가 아니거나 주어진 TID에 대해 process_wait()가
* 이미 성공적으로 호출된 경우 기다리지 않고 즉시 -1을 반환합니다.
*/
int process_wait(tid_t child_tid UNUSED) {
/* XXX: Hint) process_wait(initd)인 경우 pintos가 종료됩니다. process_wait를 구현하기
전에 여기에 무한 루프를 추가하는 것이 좋습니다. */
thread_t *child = get_child_process(child_tid);
if (child == NULL)
return -1;
sema_down(&child->wait_sema); // 자식 프로세스가 종료될 때 까지 대기.
list_remove(&child->child_elem);
sema_up(&child->exit_sema); // 자식 프로세스가 죽을 수 있도록 signal
return child->exit_status;
}
----------------------------------------------
// userprog/process.c
/** #Project 2: System Call - Exit the process. This function is called by thread_exit (). */
void process_exit(void) {/** fixed */
thread_t *curr = thread_current();
/* TODO: Your code goes here.
* TODO: Implement process termination message (see
* TODO: project2/process_termination.html).
* TODO: We recommend you to implement process resource cleanup here. */
for (int fd = 0; fd < curr->fd_idx; fd++) // FDT 비우기
close(fd);
palloc_free_multiple(curr->fdt, FDT_PAGES);
file_close(curr->runn_file); // 현재 프로세스가 실행중인 파일 종료
process_cleanup();
sema_up(&curr->wait_sema); // 자식 프로세스가 종료될 때까지 대기하는 부모에게 signal
sema_down(&curr->exit_sema); // 부모 프로세스가 종료될 떄까지 대기
}
// userprog/process.c
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());
/* Project 3 : Memory Management - Load Race 방지*/
lock_acquire(&filesys_lock); //***** fixed */
/* Open executable file. */
file = filesys_open(file_name);
if (file == NULL) {
printf("load: %s: open failed\n", file_name);
goto done;
}
/** #Project 2: 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); /*** fixed */
return success;
}
// vm/vm.c
/* Copy supplemental page table from src to dst */
bool
supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED,
struct supplemental_page_table *src UNUSED) {
/* pseudo
* spt를 순회하면서, UNINIT상태인지 확인
* UNINIT상태라면, vm_do_claim_page를 eager로 함.
*/
struct hash_iterator iter;
struct page *dst_page;
struct aux *aux;
hash_first(&iter, &src->spt_hash);
while(hash_next(&iter)) { //spt 순환
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;
switch (type) {
case VM_UNINIT: //vm_alloc_page_with_initializer로 새로운 spt에 페이지 할당.
if (!vm_alloc_page_with_initializer(page_get_type(src_page), upage, writable, src_page->uninit.init, src_page->uninit.aux))
goto err;
break;
case VM_FILE:
if(!vm_alloc_page_with_initializer(type, upage, writable, NULL, &src_page->file))
goto err;
dst_page = spt_find_page(dst, upage);
if(!file_backed_initializer(dst_page, type, NULL))
goto err;
dst_page->frame = src_page->frame;
if(!pml4_set_page(thread_current()->pml4, dst_page->va, src_page->frame->kva, src_page->writable))
goto err;
break;
case VM_ANON:
if(!vm_alloc_page(type, upage, writable))
goto err;
vm_claim_page(upage); // spt copy... ** added
struct page *dst_page = spt_find_page(dst,upage);
memcpy(dst_page->frame->kva,src_page->frame->kva,PGSIZE);
break;
default:
goto err;
}
}
return true;
err:
return false;
}
결과

test 에서 sample.txt 파일을 다른 걸 cp 해왔었다..ㅎㅎ 제대로 cp 하니 결과가 아래와 같았다.

728x90
'정글 일지' 카테고리의 다른 글
[Pintos_project3 (20)] file_backed_swap_in/out (0) | 2024.12.03 |
---|---|
[Pintos_project3 (19)] anon_swap_in, anon_swap_out (0) | 2024.12.03 |
[Pintos_project (17)] vm_file_init, file_backed_initializer (0) | 2024.12.03 |
[Pintos_project3 (16)] do_munmap, file_backed_destroy (0) | 2024.12.03 |
[Pintos_project3 (15)] do_mmap (0) | 2024.12.03 |