static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); }else{ if(base + base->property < p && p->page_link.prev == &free_list){ list_add(&free_list , &base->page_link); nr_free += n; return ; }else if(le == &free_list && p+p->property < base){ list_add_before(&free_list , &base->page_link); nr_free += n; return ; }else { struct Page *page_next = le2page(le , page_link); if(p+p->property < base && base+base->property<page_next){ list_add(p , &base->page_link); nr_free += n; return ; } } } } nr_free += n; list_add(&free_list, &(base->page_link)); }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while(1) { p = le2page(le, page_link); if (le == &free_list || p >= base) { list_add_before(le, &(base->page_link)); break; } le = list_next(le); } // Search Next le = list_next(&(base->page_link)); if(le != &free_list) { p = le2page(le, page_link); if(base + n == p) { // Link them base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } } // Search Prev le = list_prev(&(base->page_link)); if(le != &free_list) { p = le2page(le, page_link); if(p + p->property == base) { // Link them p->property += base->property; ClearPageProperty(base); list_del(&(base->page_link)); } } nr_free += n; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); int is_empty_or_last = 1; while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); if (le != &free_list) { p = le2page(le, page_link); is_empty_or_last = 0; } break; } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } if (p > base){ is_empty_or_last = 0; break; } } nr_free += n; if (is_empty_or_last) { list_add_before(&free_list, &(base->page_link)); } else { list_add_before(&(p->page_link), &(base->page_link)); } }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p, *p_end = base + n; for (p = base; p < p_end; p++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = p->property = p->ref = 0; } base->property = n; list_entry_t *e; list_entry_t *target = &free_list; for(e = list_next(&free_list); e != &free_list; ) { p = le2page(e, page_link); if(p + p->property == base) { p->property += base->property; base->property = base->flags = 0; base = p; e = list_next(e); list_del(&p->page_link); }else if(base + base->property == p) { base->property += p->property; p->property = p->flags = 0; e = list_next(e); list_del(&p->page_link); }else if(base < p) { target = e; break; }else{ e = list_next(e); } } SetPageProperty(base); list_add_before(target, &base->page_link); nr_free += n; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } } nr_free += n; //list_add(&free_list, &(base->page_link)); list_entry_t *curr=&free_list; while((curr=list_next(curr))!=&free_list){ struct Page *currp=le2page(curr,page_link); if(p<currp){ list_add_before(curr,&(base->page_link)); break; } } if(curr==&free_list){ list_add_before(curr,&(base->page_link)); } }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); struct Page* tempPG = base; for (; tempPG != base + n; tempPG++) { ClearPageReserved(tempPG); SetPageProperty(tempPG); } list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; p->property = 0; list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; base->property = 0; list_del(&(p->page_link)); base = p; } } nr_free += n; list_entry_t* rank = &free_list; while((rank=list_next(rank)) != &free_list) { if(le2page(rank, page_link) > base) break; } list_add_before(rank, &(base->page_link)); }
static void default_free_pages(struct Page* base, size_t n) { assert(0 < n); struct Page* p = base; for (; p != base + n; ++p) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t* le = list_next(&free_list); // Find insertion position while (le2page(le, page_link) < base && le != &free_list) { le = list_next(le); } le = list_prev(le); // Insert into list list_add(le, &(base->page_link)); // Merge previous one p = le2page(le, page_link); if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base->property = 0; list_del(&(base->page_link)); base = p; } // Merge next one if (list_next(&(base->page_link)) != &free_list) { p = le2page(list_next(&(base->page_link)), page_link); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); p->property = 0; list_del(&(p->page_link)); } } nr_free += n; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (PageProperty(p) && !PageReserved(p) && p->property >= n) { page = p; break; } } if (page != NULL) { le = page->page_link.prev; list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; ClearPageReserved(p); SetPageProperty(p); p->property = page->property - n; list_add(le, &(p->page_link)); } struct Page *p = page; for (; p < page + n; ++p) { SetPageReserved(p); ClearPageProperty(p); p->property = 0; list_init(&(p->page_link)); } nr_free -= n; } return page; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page* p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property= n; SetPageProperty(base); list_entry_t* le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); if (p > base) break ; le = list_next(le); } p = le2page(le, page_link); list_add_before(le, &(base->page_link)); le = list_prev(&(base->page_link)); struct Page* pp = le2page(le, page_link); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } if (pp + pp->property == base) { pp->property += base->property; ClearPageProperty(base); list_del(&(base->page_link)); } nr_free += n; }
// LAB2: below code is used to check the first fit allocation algorithm (your EXERCISE 1) // NOTICE: You SHOULD NOT CHANGE basic_check, default_check functions! static void default_check(void) { int count = 0, total = 0; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); assert(PageProperty(p)); count ++, total += p->property; } assert(total == nr_free_pages()); basic_check(); struct Page *p0 = alloc_pages(5), *p1, *p2; assert(p0 != NULL); assert(!PageProperty(p0)); list_entry_t free_list_store = free_list; list_init(&free_list); assert(list_empty(&free_list)); assert(alloc_page() == NULL); unsigned int nr_free_store = nr_free; nr_free = 0; free_pages(p0 + 2, 3); assert(alloc_pages(4) == NULL); assert(PageProperty(p0 + 2) && p0[2].property == 3); assert((p1 = alloc_pages(3)) != NULL); assert(alloc_page() == NULL); assert(p0 + 2 == p1); p2 = p0 + 1; free_page(p0); free_pages(p1, 3); assert(PageProperty(p0) && p0->property == 1); assert(PageProperty(p1) && p1->property == 3); assert((p0 = alloc_page()) == p2 - 1); free_page(p0); assert((p0 = alloc_pages(2)) == p2 + 1); free_pages(p0, 2); free_page(p2); assert((p0 = alloc_pages(5)) != NULL); assert(alloc_page() == NULL); assert(nr_free == 0); nr_free = nr_free_store; free_list = free_list_store; free_pages(p0, 5); le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); count --, total -= p->property; } assert(count == 0); assert(total == 0); }
static void check_swap(void) { //backup mem env int ret, count = 0, total = 0, i; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); assert(PageProperty(p)); count++, total += p->property; } assert(total == nr_free_pages()); cprintf("BEGIN check_swap: count %d, total %d\n", count, total); //now we set the phy pages env struct mm_struct *mm = mm_create(); assert(mm != NULL); extern struct mm_struct *check_mm_struct; assert(check_mm_struct == NULL); check_mm_struct = mm; pde_t *pgdir = mm->pgdir = boot_pgdir; assert(pgdir[0] == 0); struct vma_struct *vma = vma_create(BEING_CHECK_VALID_VADDR, CHECK_VALID_VADDR, VM_WRITE | VM_READ); assert(vma != NULL); insert_vma_struct(mm, vma); //setup the temp Page Table vaddr 0~4MB cprintf("setup Page Table for vaddr 0X1000, so alloc a page\n"); pte_t *temp_ptep = NULL; temp_ptep = get_pte(mm->pgdir, BEING_CHECK_VALID_VADDR, 1); assert(temp_ptep!= NULL); cprintf("setup Page Table vaddr 0~4MB OVER!\n"); for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { check_rp[i] = alloc_page(); assert(check_rp[i] != NULL); assert(!PageProperty(check_rp[i])); } list_entry_t free_list_store = free_list; list_init(&free_list); assert(list_empty(&free_list)); //assert(alloc_page() == NULL); unsigned int nr_free_store = nr_free; nr_free = 0; for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { free_pages(check_rp[i], 1); } assert(nr_free==CHECK_VALID_PHY_PAGE_NUM); cprintf("set up init env for check_swap begin!\n"); //setup initial vir_page<->phy_page environment for page relpacement algorithm pgfault_num = 0; check_content_set(); assert(nr_free == 0); for (i = 0; i < MAX_SEQ_NO; i++) swap_out_seq_no[i] = swap_in_seq_no[i] = -1; for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { check_ptep[i] = 0; check_ptep[i] = get_pte(pgdir, (i + 1) * 0x1000, 0); //cprintf("i %d, check_ptep addr %x, value %x\n", i, check_ptep[i], *check_ptep[i]); assert(check_ptep[i] != NULL); assert(pte2page(*check_ptep[i]) == check_rp[i]); assert((*check_ptep[i] & PTE_P)); } cprintf("set up init env for check_swap over!\n"); // now access the virt pages to test page relpacement algorithm ret = check_content_access(); assert(ret == 0); //restore kernel mem env for (i = 0; i < CHECK_VALID_PHY_PAGE_NUM; i++) { free_pages(check_rp[i], 1); } //free_page(pte2page(*temp_ptep)); free_page(pde2page(pgdir[0])); pgdir[0] = 0; mm->pgdir = NULL; mm_destroy(mm); check_mm_struct = NULL; nr_free = nr_free_store; free_list = free_list_store; le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); count--, total -= p->property; } cprintf("count is %d, total is %d\n", count, total); //assert(count == 0); cprintf("check_swap() succeeded!\n"); }
// LAB2: below code is used to check the first fit allocation algorithm (your EXERCISE 1) // NOTICE: You SHOULD NOT CHANGE basic_check, default_check functions! static void default_check(void) { // 好吧,我们现在来看一下默认的测试吧! int count = 0, total = 0; list_entry_t *le = &free_list; // free_list应该是一个文件头吧! while ((le = list_next(le)) != &free_list) { // 开始遍历 struct Page *p = le2page(le, page_link); assert(PageProperty(p)); count ++, total += p->property; // counter表示一个有多少个page,total表示一共有多少个空闲页 } assert(total == nr_free_pages()); basic_check(); struct Page *p0 = alloc_pages(5), *p1, *p2; // 分配5个页面给p0 assert(p0 != NULL); assert(!PageProperty(p0)); list_entry_t free_list_store = free_list; list_init(&free_list); assert(list_empty(&free_list)); assert(alloc_page() == NULL); // 然后分配一个页面应该为空,确实应该为空 unsigned int nr_free_store = nr_free; // 空闲的页面的数目 nr_free = 0; // 然后将他们全部变为0 free_pages(p0 + 2, 3); // 这个玩意能free吗? assert(alloc_pages(4) == NULL); // 因为nr_free=3 assert(PageProperty(p0 + 2) && p0[2].property == 3); assert((p1 = alloc_pages(3)) != NULL); // 给p1分配3块,现在nr_free=0 assert(alloc_page() == NULL); assert(p0 + 2 == p1); p2 = p0 + 1; free_page(p0); // 好吧,释放一个页面, nr_free=1 free_pages(p1, 3); // 现在nr_free = 4 assert(PageProperty(p0) && p0->property == 1); assert(PageProperty(p1) && p1->property == 3); /** p0 p2 p1 end * | | | | | | * ------------------------------- * | N N N N | * | | * ------------------------------- */ assert((p0 = alloc_page()) == p2 - 1); // 这里出错了。我倒是要看一看啦!这里应该不会出错啊,参照上面的图,重新分配的话,会分配p0,恰好是p2-1 free_page(p0); assert((p0 = alloc_pages(2)) == p2 + 1); // 这里是测试first fit的 /** start p2 p0 end * | | | | | | * ------------------------------- * | N N | * | | * ------------------------------- */ free_pages(p0, 2); free_page(p2); /** start p2 p0 end * | | | | | | * ------------------------------- * | N N N N N | * | | * ------------------------------- */ assert((p0 = alloc_pages(5)) != NULL); assert(alloc_page() == NULL); assert(nr_free == 0); nr_free = nr_free_store; // 恢复原来的样子 free_list = free_list_store; free_pages(p0, 5); le = &free_list; while ((le = list_next(le)) != &free_list) { // 又要开始遍历了,这里主要是测试经过这么折腾之后,没有出现页丢失的情况 struct Page *p = le2page(le, page_link); count --, total -= p->property; } assert(count == 0); assert(total == 0); }
/*buddy_check - Validate the correctness of buddy system. */ static void buddy_check(void){ assert((1 << (MAX_ORD-2)) >= KMEMSIZE/MIN_BLOCK && (1 << (MAX_ORD-3)) < KMEMSIZE/MIN_BLOCK); uint32_t backup = nr_free; struct Page* p1 = buddy_alloc_pages(1); assert(backup == nr_free + 1); assert(PageProperty(p1)); assert(p1->property == 1); backup = nr_free; struct Page* p2 = buddy_alloc_pages(3); assert(backup == nr_free + 4); assert(PageProperty(p2)); assert(p2->property == 4); backup = nr_free; buddy_free_pages(p1); assert(backup == nr_free - 1); assert(!PageProperty(p1)); assert(p1->property == 0); backup = nr_free; buddy_free_pages(p2); assert(backup == nr_free - 4); backup = nr_free; p1 = buddy_alloc_pages(53); assert(backup == nr_free + 64); assert(PageProperty(p1)); assert(p1->property == 64); backup = nr_free; p2 = buddy_alloc_pages(896); assert(backup == nr_free + 1024); assert(PageProperty(p2)); assert(p2->property == 1024); backup = nr_free; buddy_free_pages(p1); assert(backup == nr_free - 64); assert(!PageProperty(p1)); assert(p1->property == 0); backup = nr_free; buddy_free_pages(p2); assert(backup == nr_free - 1024); assert(!PageProperty(p2)); assert(p2->property == 0); backup = nr_free; p1 = buddy_alloc_pages((1<<13) - 13); assert(backup == nr_free + (1<<13)); assert(PageProperty(p1)); assert(p1->property == (1<<13)); backup = nr_free; p2 = buddy_alloc_pages((1<<13) - 13); assert(backup == nr_free + (1<<13)); assert(PageProperty(p2)); assert(p1->property == (1<<13)); struct Page *p3, *p4; backup = nr_free; p3 = buddy_alloc_pages((1<<12) - 12); assert(backup == nr_free + (1<<12)); assert(PageProperty(p3)); assert(p3->property == (1<<12)); backup = nr_free; p4 = buddy_alloc_pages((1<<12) - 12); assert(backup == nr_free + (1<<12)); assert(PageProperty(p4)); assert(p4->property == (1<<12)); backup = nr_free; buddy_free_pages(p1); assert(backup == nr_free - (1<<13)); assert(!PageProperty(p1)); assert(p1->property == 0); backup = nr_free; buddy_free_pages(p2); assert(backup == nr_free - (1<<13)); assert(!PageProperty(p2)); assert(p2->property == 0); backup = nr_free; buddy_free_pages(p3); assert(backup == nr_free - (1<<12)); assert(!PageProperty(p3)); assert(p3->property == 0); backup = nr_free; buddy_free_pages(p4); assert(backup == nr_free - (1<<12)); assert(!PageProperty(p4)); assert(p4->property == 0); struct Page* p[100]; int i; for(i = 0;i<100;i++){ p[i] = buddy_alloc_pages(1); assert(!PageReserved(p[i])); assert(PageProperty(p[i])); assert(p[i]->property == 1); } for(i = 0;i<100;i++){ buddy_free_pages(p[i]); assert(!PageProperty(p[i])); assert(p[i]->property == 0); } }