[Pintos-KAIST] Project 3 : Anonymous Page

์œ ์„ ยท2024๋…„ 5์›” 17์ผ
0

Pintos - KAIST

๋ชฉ๋ก ๋ณด๊ธฐ
12/16
post-thumbnail

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB ๋ ˆํฌ์ง€ํ† ๋ฆฌ
๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB Anonymous Page ์ด์Šˆ

๊ณผ์ œ ์„ค๋ช…

๐Ÿ’ก Anonymous page๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” non-disk based image๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

Anonymous Page๋ž€?

ํŒŒ์ผ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” file-backed page์™€ ๋‹ฌ๋ฆฌ, ์ด๋ฆ„์ด ์ง€์ •๋œ ํŒŒ์ผ ์†Œ์Šค๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— anonymous๋ผ๊ณ  ๋ถˆ๋ฆฌ๋ฉฐ, ์Šคํƒ๊ณผ ํž™ ์˜์—ญ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.

  • anon-page๋Š” include/vm/anon.h์— ์„ ์–ธ๋˜์–ด์žˆ๋‹ค.
  • ํ˜„์žฌ๋Š” ๊ตฌ์กฐ์ฒด๊ฐ€ ๋น„์–ด์žˆ๋‹ค.

Page Initialization with Lazy Loading

  • Demanding Paging ์ด๋ผ๊ณ ๋„ ํ•œ๋‹ค.

  • ์ง€์—ฐ ๋กœ๋”ฉ(lazy loading)์€ ํ•„์š”์‹œ์ ๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์˜ ๋กœ๋”ฉ์„ ์ง€์—ฐ์‹œํ‚จ๋‹ค. -> ์‹ค์ œ ๋‚ด์šฉ์ด ๋กœ๋“œ๋˜๋Š” ์‹œ์ ์€ page fault๊ฐ€ ๋ฐœ์ƒํ• ๋•Œ!

  • ํŽ˜์ด์ง€๊ฐ€ ํ• ๋‹น๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์€ ๋Œ€์‘๋˜๋Š” ํŽ˜์ด์ง€ ๊ตฌ์กฐ์ฒด๋Š” ์žˆ์ง€๋งŒ ์—ฐ๊ฒฐ๋œ ๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ํ”„๋ ˆ์ž„์€ ์•„์ง ์—†๊ณ , ํŽ˜์ด์ง€์˜ ์‹ค์ œ ์ฝ˜ํ…์ธ ๋Š” ์•„์ง ๋กœ๋“œ๋˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•œ๋‹ค.

  • ํŽ˜์ด์ง€ ํดํŠธ๋กœ ์ธํ•ด ์‹ค์ œ๋กœ ์ฝ˜ํ…์ธ ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋กœ๋“œ๋œ๋‹ค. (ํŽ˜์ด์ง€ ํดํŠธ๋กœ ์‹œ๊ทธ๋„์„ ๋ฐ›์Œ)

  • ์„ธ ๊ฐ€์ง€ ํŽ˜์ด์ง€ ํƒ€์ž…(VM_UNINIT, VM_ANON, VM_FILE)์„ ๊ฐ€์ง€๋Š”๋ฐ ๊ฐ ํŽ˜์ด์ง€๋ณ„๋กœ ์ดˆ๊ธฐํ™” ๋ฃจํ‹ด์ด ๋‹ค๋ฅด๋‹ค.

  • ํŽ˜์ด์ง€ ํดํŠธ ์ฒ˜๋ฆฌ ์ ˆ์ฐจ ์ค‘์— uninit_initialize ์„ ํ˜ธ์ถœํ•˜๊ณ  ์ด์ „์— ์„ค์ •ํ•œ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

    • ์ต๋ช… ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜ : 'anon_initializer'
    • ํŒŒ์ผ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜ : 'file_backed_initializer'
  • ํŽ˜์ด์ง€๋Š” ์ดˆ๊ธฐํ™”โ†’(ํŽ˜์ด์ง€ ํดํŠธ โ†’ ์ง€์—ฐ ๋กœ๋”ฉ โ†’ ์Šค์™‘ ์ธ โ†’ ์Šค์™‘ ์•„์›ƒ โ†’ โ€ฆ) โ†’ ์‚ญ์ œ ๋ผ๋Š” cycle์„ ๊ฐ€์ง„๋‹ค.

  • ํŽ˜์ด์ง€ ํƒ€์ž…(ํ˜น์€ VM_TYPE)๋ณ„ ์ดˆ๊ธฐํ™” ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅธ ๊ฒƒ์ฒ˜๋Ÿผ, cycle์˜ ์ „ํ™˜๋งˆ๋‹ค ํŽ˜์ด์ง€ ํƒ€์ž…๋ณ„๋กœ ๋‹ค๋ฅธ ํ”„๋กœ์‹œ์ €๊ฐ€ ์š”๊ตฌ๋จ

    ๐Ÿ’ก ๊ฐ ํŽ˜์ด์ง€ ํƒ€์ž…์— ๋”ฐ๋ฅธ ์ „ํ™˜(transition processes) ๊ณผ์ •์„ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.


๊ตฌํ˜„

1. vm_alloc_page_with_initializer() ๊ตฌํ˜„

  • vm/vm.c
  • upage๊ฐ€ ์ด๋ฏธ ์‚ฌ์šฉ ์ค‘์ธ์ง€ ํ™•์ธํ•œ๋‹ค.
  • ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • type์— ๋”ฐ๋ผ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.
  • "uninit" ํƒ€์ž…์˜ ํŽ˜์ด์ง€๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
  • ํ•„๋“œ ์ˆ˜์ •์€ uninit_new๋ฅผ ํ˜ธ์ถœํ•œ ์ดํ›„์— ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ƒ์„ฑํ•œ ํŽ˜์ด์ง€๋ฅผ SPT์— ์ถ”๊ฐ€ํ•œ๋‹ค.
bool
vm_alloc_page_with_initializer (enum vm_type type, void *upage, bool writable,
		vm_initializer *init, void *aux) {

	ASSERT (VM_TYPE(type) != VM_UNINIT)

	struct supplemental_page_table *spt = &thread_current ()->spt;

	/* Check wheter the upage is already occupied or not. */
	if (spt_find_page (spt, upage) == NULL) {

		/** #project3-Anonymous Page */
		struct page *page = malloc(sizeof(struct page));

		if (!page)
			goto err;

		typedef bool (*initializer_by_type)(struct page *, enum vm_type, void *);
		initializer_by_type initializer = NULL;

		switch (VM_TYPE(type))
		{
		case VM_ANON:
			initializer = anon_initializer;
			break;
		case VM_FILE:
			initializer = file_backed_initializer;
			break;
		}

		uninit_new(page, upage, init, type, aux, initializer);
		page->writable = writable;
		
		return spt_insert_page(spt, page);
	}
err:
	return false;
}

2. vm_load_arg ์ž๋ฃŒ๊ตฌ์กฐ ์ถ”๊ฐ€

  • include/vm/vm.h
/** Project 3-Memory Mapped Files */
struct vm_load_arg
{
	struct file *file;
	off_t ofs;
	uint32_t read_bytes;
	uint32_t zero_bytes;
};

3. load_segment(), lazy_load_segment() ์ˆ˜์ •

3-1. load_segment(),

  • userprog/process.c
  • ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ upage์— ๋กœ๋“œํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
static bool
load_segment (struct file *file, off_t ofs, uint8_t *upage,
		uint32_t read_bytes, uint32_t zero_bytes, bool writable) {
	ASSERT ((read_bytes + zero_bytes) % PGSIZE == 0);
	ASSERT (pg_ofs (upage) == 0);
	ASSERT (ofs % PGSIZE == 0);

	file_seek (file, ofs);
	while (read_bytes > 0 || zero_bytes > 0) {
		/* Do calculate how to fill this page.
		 * We will read PAGE_READ_BYTES bytes from FILE
		 * and zero the final PAGE_ZERO_BYTES bytes. */
		size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
		size_t page_zero_bytes = PGSIZE - page_read_bytes;

		/* Get a page of memory. */
		uint8_t *kpage = palloc_get_page (PAL_USER);
		if (kpage == NULL)
			return false;

		/* Load this page. */
		if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes) {
			palloc_free_page (kpage);
			return false;
		}
		memset (kpage + page_read_bytes, 0, page_zero_bytes);

		/* Add the page to the process's address space. */
		if (!install_page (upage, kpage, writable)) {
			printf("fail\n");
			palloc_free_page (kpage);
			return false;
		}

		/* Advance. */
		read_bytes -= page_read_bytes;
		zero_bytes -= page_zero_bytes;
		upage += PGSIZE;
	}
	return true;
}

3-2. lazy_load_segment()

  • userprog/process.c
  • ์ด ํ•จ์ˆ˜๋Š” ์‹คํ–‰ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ํŽ˜์ด์ง€๋กœ ๋กœ๋”ฉํ•˜๋Š” ํ•จ์ˆ˜์ด๋ฉฐ ์ฒซ๋ฒˆ์งธ page fault๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ ํ˜ธ์ถœ๋œ๋‹ค.
static bool
lazy_load_segment (struct page *page, void *aux) {
	/** Project 3-Anonymous Page */
    struct vm_load_arg *aux_p = aux;
    struct file *file = aux_p->file;
    off_t offset = aux_p->ofs;
    size_t page_read_bytes = aux_p->read_bytes;
    size_t page_zero_bytes = PGSIZE - page_read_bytes;

    file_seek(file, offset);                                                             
    if (file_read(file, page->frame->kva, page_read_bytes) != (off_t)page_read_bytes) {  
        palloc_free_page(page->frame->kva);                                            
        return false;
    }

    memset(page->frame->kva + page_read_bytes, 0, page_zero_bytes);  

    return true;
}

4. setup_stack() ์ˆ˜์ • ๋ฐ stack์šฉ ํฌ์ธํ„ฐ ์ƒ์„ฑ

4-1. stack์šฉ ํฌ์ธํ„ฐ ์ƒ์„ฑ

  • include/threads/thread.h
  • ์Šคํƒ์˜ ๋งจ ์•„๋ž˜ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ
  • ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ƒํ–ฅ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํŽ˜์ด์ง€ํฌ๊ธฐ ๋งŒํผ ๋นผ์ค€ ๋’ค ๊ณต๊ฐ„์„ ํ• ๋‹นํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค!
#ifdef VM
	/* Table for whole virtual memory owned by thread. */
	struct supplemental_page_table spt;

	/** Project 3-Anonymous Page - stack์šฉ ํฌ์ธํ„ฐ ์ƒ์„ฑ*/
    void *stack_bottom;
    void *stack_pointer;
#endif

4-2. setup_stack()

  • userprog/process.c
  • ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ load ํ•จ์ˆ˜ ์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋ฉฐ, STACK์˜ ํŽ˜์ด์ง€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ์Šคํƒ ํŽ˜์ด์ง€๋Š” Lazy Loading์„ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋  ๋•Œ ์ด ํ•จ์ˆ˜๊ฐ€ ๋ถˆ๋ฆฌ๊ณ  ๋‚˜์„œ command line arguments๋ฅผ ์Šคํƒ์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ฃผ์†Œ์— ๋ฐ”๋กœ ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ๋”ฐ๋ผ์„œ, ์ด ์ฃผ์†Œ์—์„œ fault๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š”์—†์ด ๋ฐ”๋กœ ๋ฌผ๋ฆฌ ํ”„๋ ˆ์ž„์„ ํ• ๋‹น๋ฐ›์•„ ๋†“๋Š”๋‹ค.
  • ํŽ˜์ด์ง€๋ฅผ ํ• ๋‹น๋ฐ›์„ ๋•Œ ์ด ํŽ˜์ด์ง€๊ฐ€ ์Šคํƒ์˜ ํŽ˜์ด์ง€์ž„์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ณด์กฐ ๋งˆ์ปค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.(VM_MARKER_0๋ฅผ ์‚ฌ์šฉ)
static bool
setup_stack (struct intr_frame *if_) {
	bool success = false;
	void *stack_bottom = (void *) (((uint8_t *) USER_STACK) - PGSIZE);

	/** Project 3-Anonymous Page */
    if (vm_alloc_page(VM_ANON | VM_MARKER_0, stack_bottom, 1)) {  // MARKER_0๋กœ STACK์— ์žˆ๋Š” ๊ฒƒ์„ ํ‘œ์‹œ
        success = vm_claim_page(stack_bottom);

        if (success) {
            if_->rsp = USER_STACK;
            thread_current()->stack_bottom = stack_bottom;
        }
    }
	return success;
}

5. vm_try_handle_fault() ๊ตฌํ˜„

  • vm/vm.c
  • VM ๊ตฌํ˜„ ์ดํ›„๋ถ€ํ„ฐ ํŽ˜์ด์ง€ ํดํŠธ๋Š” vm_try_handle_fault๊ฐ€ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • page_fault ํ•ธ๋“ค๋Ÿฌ๋Š” ํŽ˜์ด์ง€ ํดํŠธ์— ๋Œ€ํ•œ ์ œ์–ด๊ถŒ์„ vm_try_handle_fault ์œผ๋กœ ๋„˜๊ธด๋‹ค.
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;

	/** Project 3-Anonymous Page */
	struct page *page = spt_find_page(&thread_current()->spt, addr);
   
    if (addr == NULL || is_kernel_vaddr(addr))
        return false;

    if (not_present)
    {
        page = spt_find_page(spt, addr);
        if (page == NULL)
            return false;
        if (write == 1 && page->writable == 0)
            return false;
        return vm_do_claim_page(page);
    }
    return false;
}

6. supplemental_page_table_copy() ๊ตฌํ˜„

  • vm/vm.c
  • ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ ์‹œ, spt ๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. (์ž์‹ ํ”„๋กœ์„ธ์Šค ์ƒ์„ฑ)
  • ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์˜ SPT์— ์žˆ๋Š” ๋ชจ๋“  ํŽ˜์ด์ง€๋ฅผ ๊ฐ ํƒ€์ž…์— ๋งž๊ฒŒ ํ• ๋‹น์„ ๋ฐ›๋Š”๋‹ค.
  • uninit ์ƒํƒœ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด, ์ฆ‰ ๋‚ด์šฉ์ด ๋กœ๋”ฉ๋œ ์ƒํƒœ๋ผ๋ฉด ๋ฐ”๋กœ ๋งคํ•‘์„ ์ง„ํ–‰ํ•ด์„œ ๋‚ด์šฉ๊นŒ์ง€ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
  • file-backed page์ธ ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฅธ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ anonymous page ํŒŒํŠธ์—์„œ๋Š” ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค. file-backed page๋ฅผ ํ•  ๋•Œ ์ถ”๊ฐ€ํ•œ๋‹ค.
bool
supplemental_page_table_copy (struct supplemental_page_table *dst UNUSED,
		struct supplemental_page_table *src UNUSED) {
	
	/** Project 3-Anonymous Page */
	struct hash_iterator i;
	hash_first(&i, &src->spt_hash);
	while (hash_next(&i))
	{
		struct page *src_page = hash_entry(hash_cur(&i), struct page, hash_elem);
		enum vm_type src_type = src_page->operations->type;

		if (src_type == VM_UNINIT)
		{
			vm_alloc_page_with_initializer(
				src_page->uninit.type,
				src_page->va,
				src_page->writable,
				src_page->uninit.init,
				src_page->uninit.aux);
		}
		else
		{
			if (vm_alloc_page(src_type, src_page->va, src_page->writable) && vm_claim_page(src_page->va))
			{
				struct page *dst_page = spt_find_page(dst, src_page->va);
				memcpy(dst_page->frame->kva, src_page->frame->kva, PGSIZE);
			}
		}
	}
	return true;
}

7. supplemental_page_table_kill() ๋ฐ hash_page_destroy() ๊ตฌํ˜„

  • ํŽ˜์ด์ง€ ํ•ญ๋ชฉ๋“ค์„ ์ˆœํšŒํ•˜๋ฉฐ ํ…Œ์ด๋ธ” ๋‚ด์˜ ํŽ˜์ด์ง€๋“ค์˜ ํƒ€์ž…์— ๋งž๋Š” destroy ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  • destroy ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€ ํƒ€์ž…์— ๋”ฐ๋ผ์„œ uninit_destroy ํ˜น์€ anon_destroy ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
  • hash table์€ ๋‘๊ณ  ์•ˆ์˜ ์š”์†Œ๋“ค๋งŒ ์ง€์›Œ์ค˜์•ผ ํ•œ๋‹ค.
  • hash_destroy ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด hash๊ฐ€ ์‚ฌ์šฉํ•˜๋˜ ๋ฉ”๋ชจ๋ฆฌ(hash->bucket) ์ž์ฒด๋„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, hash_destroy๊ฐ€ ์•„๋‹Œ hash_clear๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

7-1. hash_page_destroy() ์„ ์–ธ

  • include/vm/vm.h
/** Project 3-Anonymous Page */
uint64_t page_hash(const struct hash_elem *e, void *aux);
bool page_less(const struct hash_elem *a, const struct hash_elem *b, void *aux);
void hash_page_destroy(struct hash_elem *e, void *aux);
#endif  /* VM_VM_H */

7-2. hash_page_destroy() ๊ตฌํ˜„

  • vm/vm.c
/** Project 3-Anonymous Page */
void 
hash_page_destroy(struct hash_elem *e, void *aux)
{
    struct page *page = hash_entry(e, struct page, hash_elem);
    destroy(page);
    free(page);
}

7-3. supplemental_page_table_kill() ๊ตฌํ˜„

  • vm/vm.c
void
supplemental_page_table_kill (struct supplemental_page_table *spt UNUSED) {
	/** Project 3-Anonymous Page */
	hash_clear(&spt->spt_hash, hash_page_destroy);
}

8. System Calls ์ˆ˜์ •

  • userprog/syscall.c
#ifndef VM
/** project2-System Call */
void check_address(void *addr) {
    thread_t *curr = thread_current();

    if (is_kernel_vaddr(addr) || addr == NULL || pml4_get_page(curr->pml4, addr) == NULL)
        exit(-1);
}
#else
/** Project 3-Anonymous Page */
struct page *check_address(void *addr) {
    struct thread *curr = thread_current();

    if (is_kernel_vaddr(addr) || addr == NULL || !spt_find_page(&curr->spt, addr))
        exit(-1);

    return spt_find_page(&curr->spt, addr);
}
#endif
  • include/userprog/syscall.h
/** Project 3-Anonymous Page */
#ifndef VM
void check_address(void *addr);
#else
/** #Project 3: Anonymous Page */
struct page *check_address(void *addr);
#endif

9. page_fault ์กฐ๊ฑด ์ˆ˜์ •

  • userprog/exception.c
	/** Project 3-Anonymous Page */
	if ((!not_present && write) || (fault_addr < 0x400000 || fault_addr >= USER_STACK))
	{
		exit(-1);
	}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

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
FAIL tests/vm/pt-grow-stack
pass tests/vm/pt-grow-bad
FAIL tests/vm/pt-big-stk-obj
pass tests/vm/pt-bad-addr
pass tests/vm/pt-bad-read
pass tests/vm/pt-write-code
FAIL tests/vm/pt-write-code2
FAIL tests/vm/pt-grow-stk-sc
pass tests/vm/page-linear
pass tests/vm/page-parallel
pass tests/vm/page-merge-seq
FAIL tests/vm/page-merge-par
FAIL tests/vm/page-merge-stk
FAIL tests/vm/page-merge-mm
pass tests/vm/page-shuffle
FAIL tests/vm/mmap-read
FAIL tests/vm/mmap-close
FAIL tests/vm/mmap-unmap
FAIL tests/vm/mmap-overlap
FAIL tests/vm/mmap-twice
FAIL tests/vm/mmap-write
FAIL tests/vm/mmap-ro
FAIL tests/vm/mmap-exit
FAIL tests/vm/mmap-shuffle
pass tests/vm/mmap-bad-fd
FAIL tests/vm/mmap-clean
FAIL tests/vm/mmap-inherit
FAIL tests/vm/mmap-misalign
FAIL tests/vm/mmap-null
FAIL tests/vm/mmap-over-code
FAIL tests/vm/mmap-over-data
FAIL tests/vm/mmap-over-stk
FAIL 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
FAIL tests/vm/mmap-off
FAIL tests/vm/mmap-bad-off
FAIL tests/vm/mmap-kernel
FAIL tests/vm/lazy-file
pass tests/vm/lazy-anon
FAIL tests/vm/swap-file
FAIL tests/vm/swap-anon
FAIL tests/vm/swap-iter
FAIL 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
FAIL tests/vm/cow/cow-simple
33 of 141 tests failed.
profile
Sunny Day!

0๊ฐœ์˜ ๋Œ“๊ธ€