미소를뿌리는감자의 코딩

[Pintos_project3 (21)] extra 본문

정글 일지

[Pintos_project3 (21)] extra

미뿌감 2024. 12. 3. 23:13
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