미소를뿌리는감자의 코딩

[Pintos_project3 (14)] vm_try_handle_fault, vm_stack_growth 본문

정글 일지

[Pintos_project3 (14)] vm_try_handle_fault, vm_stack_growth

미뿌감 2024. 12. 3. 00:10
728x90

1. 개요

이번에 Stack Growth에 대해서 다루어 보려고 한다.

stack은 init으로 1개의 페이지를 먼저 초기화를 하고 시작한다.

하지만 1개의 페이지보다 더 많은 stack을 이용하려고 할 시, 어떻게 될 것인가?

 

이를 다루기 위한 것이 이번 단원의 목표이다.

따라서, page_fault가 일어났을 시, 이것이 일반적인 page fault인지 아니면, stack이 초과되어서 나는 page_fault인지 파악해야 한다.

만약에 spt에서 page를 찾을 수 없으면, false를 반환했던 것과 달리, 코드를 작성해 주어야 한다.

 

커널 모드에서 발생한 페이지 fault의 경우 sp가 저장되지 않는다. 

따라서, 쓰레기 값이 저장되어 있을 수 있기 때문에 유저 모드에서 커널 모드로 전환 시, sp를 struct thread에 저장해 주어야 한다.

 

 

2. 본문

코드를 보면서 확인해 보자.

/** Project 3: Memory Management - Return true on success */
bool vm_try_handle_fault(struct intr_frame *f UNUSED, void *addr UNUSED, bool user UNUSED, bool write UNUSED, bool not_present UNUSED) {
    struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
    struct page *page = spt_find_page(&thread_current()->spt, addr);

    /* TODO: Validate the fault */
    if (addr == NULL || is_kernel_vaddr(addr))
        return false;


    /** Project 3: Copy On Write (Extra) - 이전에 만들었던 페이지인데 swap out되어서 현재 spt에서 삭제하였을 때 stack_growth 대신 claim_page를 하기 위해 조건 분기 */
    if (!page) {
        /** Project 3: Stack Growth - stack growth로 처리할 수 있는 경우 */
        /* stack pointer 아래 8바이트는 페이지 폴트 발생 & addr 위치를 USER_STACK에서 1MB로 제한 */
        void *stack_pointer = user ? f->rsp : thread_current()->stack_pointer;
        if (stack_pointer - 8 <= addr && addr >= STACK_LIMIT && addr <= USER_STACK) { 
			/* stack_pointer - 8 <= addr ; 스택 overflow가 맞는지 확인 sp' 8 byte 내에 있는 요청인지 확인
			 * addr >= STACK_LIMIT ; 스택이 시스템의 허용 범위를 초과하지 않는지 확인. 즉, 1MB를 초과하지 않는지 확인
			 * addr <= USER_STACK ; 스택은 USER_STACK에서 아래로 성장한다. 하지만, USER_STACK보다 위의 addr에 접근하는 건 잘못된 접근이므로 이를 확인하여 준다.
			 */
            vm_stack_growth(thread_current()->stack_bottom - PGSIZE); // vm의 stack의 제한을 늘림. 1 PAGE 만큼.
            return true;
        }
        return false;
    }

    return vm_do_claim_page(page);  // demand page 수행
}

 

추가적인 stack page를 할당하기에 앞서 확인해야하는 것이 3가지 있다. 이들 모두를 충족시켜야 한다.

  1. 스택이 초과되어서 난 page fault가 맞는지 확인한다. sp의 8 Byte이내에 addr가 있는 지 확인.
  2. 스택의 시스템의 허용 범위(STACK_LIMIT)을 초과하지 않는지 확인한다. stack이 부족하더라도, 시스템이 허용한 stack 할당 용량을 벗어나기 때문에 추가적인 스택 페이지를 할당할 수 없다.
  3. 스택은 USER_STACK에서 아래로 성장한다. 만약 USER_STACK보다 위에 있는 addr라면, 이는 스택 초과로 인한 page fault가 아니기 때문에, false를 반환한다.
/* Growing the stack. */
static void
vm_stack_growth (void *addr UNUSED) {
	/* rsp 기준을 늘리기 */
	bool success = false;
	if (vm_alloc_page(VM_ANON | VM_MARKER_0, addr, true)) { // 현재 stack_bottom에서 1 PAGE만큼 아래의 주소에 대해서 vm_alloc_page를 시도.
		success = vm_claim_page(addr);

		if (success) {
			thread_current()->stack_bottom -= PGSIZE;
		}
	}
}

3. 결과

3개의 테스트가 더 통과했음을 할 수 있다.

728x90