// swap_remove_entry - call swap_list_del to remove page from swap hash list, // - and call swap_free_page to generate a free page void swap_remove_entry(swap_entry_t entry) { size_t offset = swap_offset(entry); assert(mem_map[offset] > 0); if (-- mem_map[offset] == 0) { struct Page *page = swap_hash_find(entry); if (page != NULL) { if (page_ref(page) != 0) { return ; } swap_list_del(page); swap_free_page(page); } mem_map[offset] = SWAP_UNUSED; } }
// try_alloc_swap_entry - try to alloc a unused swap entry static swap_entry_t try_alloc_swap_entry(void) { static size_t next = 1; size_t empty = 0, zero = 0, end = next; do { switch (mem_map[next]) { case SWAP_UNUSED: empty = next; break; case 0: if (zero == 0) { zero = next; } break; } if (++ next == max_swap_offset) { next = 1; } } while (empty == 0 && next != end); swap_entry_t entry = 0; if (empty != 0) { entry = (empty << 8); } else if (zero != 0) { entry = (zero << 8); struct Page *page = swap_hash_find(entry); assert(page != NULL && PageSwap(page)); swap_list_del(page); if (page_ref(page) == 0) { swap_free_page(page); } else { swap_page_del(page); } mem_map[zero] = SWAP_UNUSED; } static unsigned int failed_counter = 0; if (entry == 0 && ((++ failed_counter) % 0x1000) == 0) { warn("swap: try_alloc_swap_entry: failed too many times.\n"); } return entry; }
/** * alloc_phys_page - varaa fyysisen muistisivun * @noswap: 1, jos sivua ei saa swapata kovalevylle **/ uint_t alloc_phys_page(int noswap) { uint_t i, j; uint_t page = 0; if (!memory.ram_pages_free) { page = swap_free_page(); if (page) { i = page / 32; j = page % 32; goto loytyi; } panic("MEM: Out of memory!"); return 0; } i = first_phys_pages_not_alloced; for (i = first_phys_pages_not_alloced; i < PHYS_PAGE_BITMAP_LEN32; i++) { if (phys_pages_alloced[i] == 0xffffffff) { continue; } for (j = 0; j < 32; j++) { if (phys_pages_alloced[i] & (1 << j)) { continue; } // TODO: first_phys_pages_not_alloced: sahausta vai silmukkaa? first_phys_pages_not_alloced = i; page = (i * 32) + j; goto loytyi; } } panic("MEM: Out of RAM and failed counting it!"); return 0; loytyi:; if (get_bit(phys_pages_alloced[i], j) == 0) { memory.ram_pages_free--; phys_pages_alloced[i] = set_bit(phys_pages_alloced[i], j, 1); } phys_pages_noswap[i] = set_bit(phys_pages_noswap[i], j, noswap); return page; }
// 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; }