int swap_out(struct mm_struct *mm, int n, int in_tick) { int i; for (i = 0; i != n; ++ i) { uintptr_t v; //struct Page **ptr_page=NULL; struct Page *page; // cprintf("i %d, SWAP: call swap_out_victim\n",i); int r = sm->swap_out_victim(mm, &page, in_tick); if (r != 0) { cprintf("i %d, swap_out: call swap_out_victim failed\n",i); break; } //assert(!PageReserved(page)); //cprintf("SWAP: choose victim page 0x%08x\n", page); v=page->pra_vaddr; pte_t *ptep = get_pte(mm->pgdir, v, 0); assert((*ptep & PTE_P) != 0); //Lab3_X: 2013011509 //Only write back if dirty if (page->need_write_back) { if (swapfs_write((page->pra_vaddr / PGSIZE + 1) << 8, page) != 0) { cprintf("SWAP: failed to save\n"); sm->map_swappable(mm, v, page, 0); continue; } else { cprintf( "swap_out: i %d, store page in vaddr 0x%x to disk swap " "entry %d\n", i, v, page->pra_vaddr / PGSIZE + 1); *ptep = (page->pra_vaddr / PGSIZE + 1) << 8; free_page(page); page->has_backup = 1; } } else { *ptep = (page->pra_vaddr / PGSIZE + 1) << 8; free_page(page); } tlb_invalidate(mm->pgdir, v); } return i; }
// page_launder - try to move page to swap_active_list OR swap_inactive_list, // - and call swap_fs_write to swap out pages in swap_inactive_list int page_launder(void) { size_t maxscan = nr_inactive_pages, free_count = 0; list_entry_t *list = &(inactive_list.swap_list), *le = list_next(list); while (maxscan -- > 0 && le != list) { struct Page *page = le2page(le, swap_link); le = list_next(le); if (!(PageSwap(page) && !PageActive(page))) { panic("inactive: wrong swap list.\n"); } swap_list_del(page); if (page_ref(page) != 0) { swap_active_list_add(page); continue ; } swap_entry_t entry = page->index; if (!try_free_swap_entry(entry)) { if (PageDirty(page)) { ClearPageDirty(page); swap_duplicate(entry); if (swapfs_write(entry, page) != 0) { SetPageDirty(page); } mem_map[swap_offset(entry)] --; if (page_ref(page) != 0) { swap_active_list_add(page); continue ; } if (PageDirty(page)) { swap_inactive_list_add(page); continue ; } try_free_swap_entry(entry); } } free_count ++; swap_free_page(page); } return free_count; }