# thread.h
void* stack_bottom; // stack의 최하위 주소 저장할 변수
void* rsp_stack; // stack 늘리기 위해 rsp 저장할 변수
#process.c
/* Create a PAGE of stack at the USER_STACK. Return true on success.
* USER_STACK 설정하는 역할로 유저 스택 페이지를 할당하고 초기화 한다. */
static bool setup_stack(struct intr_frame *if_) {
bool success = false;
// stack_bottom: 스택 페이지의 가장 아래 부분을 가리키는 포인터
// USER_STACK은 사용자 스택의 최상위 주소이며 여기에 PGSIZE만큼 뺴줌으로써 스택의 맨 아래 주소를 계산한다.
// 주의) 일반적으로 stack의 bottom은 스택의 최상위 주소이지만 코드상에서의 stack bottom은 가장 낮은 주소를 나타냄
void *stack_bottom = (void *)(((uint8_t *)USER_STACK) - PGSIZE); // 0x4747F000
// anon 타입의 사용자 스택 페이지 할당 (쓰기 가능)
if (vm_alloc_page(VM_ANON, stack_bottom, true)) {
if (vm_claim_page(stack_bottom)) { // 페이지를 물리 메모리에 연결
if_->rsp = USER_STACK; // 성공적으로 연결되면 rsp를 USER_STACK(최상위 주소)으로 설정 -> 스택은 높은 주소부터 쌓이니까!
thread_current()->stack_bottom = stack_bottom; // 스택의 끝 부분 저장
success = true;
}
}
return success;
}
# vm.c
bool
vm_try_handle_fault (struct intr_frame *f UNUSED, void *addr UNUSED,
bool user UNUSED, bool write UNUSED, bool not_present UNUSED) {
struct thread *curr = thread_current();
struct supplemental_page_table *spt UNUSED = &thread_current()->spt;
// 페이지 폴트가 발생한 가상 주소 및 인자들이 유효한지 체크
if (!is_user_vaddr(addr))
return false;
// 스택 증가로 page fault 예외를 처리할 수 있는지 확인 후 vm_stack_growth 호출
// rsp가 유효하면 스택그로우 호출
if (USER_STACK - (1<<20) <= addr && curr->rsp_stack-8 <= addr && addr <= curr->stack_bottom)
vm_stack_growth(addr);
// 접근한 메모리가 물리 페이지와 매핑 되지 않은 경우
if (not_present) {
struct page *page = spt_find_page(spt, addr);
if (!page)
return false;
// read only page에 write 하려는 상황인지 확인
if (write && !page->writable)
return false;
return vm_do_claim_page (page);
}
return false;
}
static void
vm_stack_growth (void *addr UNUSED) {
// 하나 이상의 anon 페이지를 할당하여 스택 크기를 늘림
// addr은 faulted 주소에서 유효한 주소
addr = pg_round_down(addr);
if (vm_alloc_page(VM_ANON, addr, true))
thread_current()->stack_bottom -= PGSIZE; // stack_bottom 갱신해줌
}
주석으로 정리..