Пример #1
0
// 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;
    }
}
Пример #2
0
// 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;
}
Пример #3
0
/**
* 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;
}
Пример #4
0
// 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;
}