示例#1
0
文件: lpage.c 项目: ShaoyuC/OS161
/*
 * lpage_evict: Evict an lpage from physical memory.
 *
 * Synchronization: lock the lpage while evicting it. We come here
 * from the coremap and should
 * have pinned the physical page. This is why we must not hold lpage
 * locks while entering the coremap code.
 */
void
lpage_evict(struct lpage *lp)
{
	KASSERT(lp != NULL);
	lpage_lock(lp);

	KASSERT(lp->lp_paddr != INVALID_PADDR);
	KASSERT(lp->lp_swapaddr != INVALID_SWAPADDR);

	/* if the page is dirty, swap_pageout */
	if (LP_ISDIRTY(lp)) {
        lpage_unlock(lp); // release lock before doing I/O

		KASSERT(lock_do_i_hold(global_paging_lock));
		KASSERT(coremap_pageispinned(lp->lp_paddr));

        swap_pageout((lp->lp_paddr & PAGE_FRAME), lp->lp_swapaddr);
        lpage_lock(lp);
        KASSERT((lp->lp_paddr & PAGE_FRAME) != INVALID_PADDR);

		/* update stats */
		spinlock_acquire(&stats_spinlock);
		ct_write_evictions++;
	    DEBUG (DB_VM, "lpage_evict: evicting Dirty page 0x%x\n",
	    		(lp->lp_paddr & PAGE_FRAME));
		spinlock_release(&stats_spinlock);

	} else {

		/* if page is clean, just update stats */
		spinlock_acquire(&stats_spinlock);
		ct_discard_evictions++;
	    DEBUG (DB_VM, "lpage_evict: evicting Clean page 0x%x\n",
	    		(lp->lp_paddr & PAGE_FRAME));
		spinlock_release(&stats_spinlock);
	}


	/* modify PTE to indicate that the page is no longer in memory. */
	lp->lp_paddr = INVALID_PADDR;

	lpage_unlock(lp);
}
示例#2
0
文件: lpage.c 项目: Derek-lai-/OS161
/*
 * lpage_evict: Evict an lpage from physical memory.
 *
 * Synchronization: lock the lpage while accessing it. We come here
 * from the coremap and should have the global paging lock and should 
 * have pinned the physical page (see coremap.c:do_evict()). 
 * This is why we must not hold lpage locks while entering the coremap code.
 *
 * Similar to lpage_fault, the lpage lock should not be held while performing
 * the page out (if one is needed).
 */
void
lpage_evict(struct lpage *lp)
{
	paddr_t pa;
    off_t swapaddr;
    
	KASSERT(lock_do_i_hold(global_paging_lock));
	KASSERT(lp != NULL);
    lpage_lock(lp);
    swapaddr = lp->lp_swapaddr;
    pa = lp->lp_paddr & PAGE_FRAME;
	KASSERT(pa != INVALID_PADDR);
	if (LP_ISDIRTY(lp)) {
		lpage_unlock(lp);
		LP_CLEAR(lp, LPF_DIRTY);
		swap_pageout(pa, swapaddr);
		lpage_lock(lp);
	}
    lp->lp_paddr = INVALID_PADDR;
    lpage_unlock(lp);
}
示例#3
0
文件: lpage.c 项目: Adam-Koza/A3
/*
 * lpage_evict: Evict an lpage from physical memory.
 *
 * Synchronization: lock the lpage while accessing it. We come here
 * from the coremap and should have the global paging lock and should 
 * have pinned the physical page (see coremap.c:do_evict()). 
 * This is why we must not hold lpage locks while entering the coremap code.
 *
 * Similar to lpage_fault, the lpage lock should not be held while performing
 * the page out (if one is needed).
 */
void
lpage_evict(struct lpage *lp)
{

	paddr_t physical_address;
	off_t swap_address;

	// Lock the lpage while accessing it.
	KASSERT(lp != NULL);
	lpage_lock(lp);

	// Obtain the physical & swap address'
	physical_address = lp->lp_paddr & PAGE_FRAME;
	swap_address = lp->lp_swapaddr;

	// If the page is stored in RAM memory...
	if (physical_address != INVALID_PADDR) {
		DEBUG(DB_VM, "lpage_evict: Moving page from paddr 0x%x to swapaddr 0x%llx\n", physical_address, swap_address);

		// If page is dirty..
		if (LP_ISDIRTY(lp)) {
			// Move page into swapspace.
			lpage_unlock(lp);
			swap_pageout(physical_address, swap_address);
		  	LP_CLEAR(lp, LPF_DIRTY);
		  	lpage_lock(lp);
		}

		// Remove page from physical memory.
		lp->lp_paddr = INVALID_PADDR;
		lpage_unlock(lp);

	}
	else {
		lpage_unlock(lp);
	}

}
示例#4
0
文件: lpage.c 项目: ShaoyuC/OS161
/*
 * lpage_copy: create a new lpage and copy data from another lpage.
 *
 * The synchronization for this is kind of unpleasant. We do it like
 * this:
 *
 *      1. Create newlp.
 *      2. Materialize a page for newlp, so it's locked and pinned.
 *      3. Lock and pin oldlp.
 *      4. Extract the physical address and swap address.
 *      5. If oldlp wasn't present,
 *      5a.    Unlock oldlp.
 *      5b.    Page in.
 *      5c.    This pins the page in the coremap.
 *      5d.    Leave the page pinned and relock oldlp.
 *      5e.    Assert nobody else paged the page in.
 *      6. Copy.
 *      7. Unlock the lpages first, so we can enter the coremap.
 *      8. Unpin the physical pages.
 *      
 */
int
lpage_copy(struct lpage *oldlp, struct lpage **lpret)
{
	struct lpage *newlp;
	paddr_t newpa, oldpa;
	off_t swa;
	int result;

	result = lpage_materialize(&newlp, &newpa);
	if (result) {
		return result;
	}
	KASSERT(coremap_pageispinned(newpa));

	/* Pin the physical page and lock the lpage. */
	lpage_lock_and_pin(oldlp);
	oldpa = oldlp->lp_paddr & PAGE_FRAME;

	/*
	 * If there is no physical page, we allocate one, which pins
	 * it, and then (re)lock the lpage. Since we are single-
	 * threaded (if we weren't, we'd hold the address space lock
	 * to exclude sibling threads) nobody else should have paged
	 * the page in behind our back.
	 */
	if (oldpa == INVALID_PADDR) {
		/*
		 * XXX this is mostly copied from lpage_fault
		 */
		swa = oldlp->lp_swapaddr;
		lpage_unlock(oldlp);
		oldpa = coremap_allocuser(oldlp);
		if (oldpa == INVALID_PADDR) {
			coremap_unpin(newlp->lp_paddr & PAGE_FRAME);
			lpage_destroy(newlp);
			return ENOMEM;
		}
		KASSERT(coremap_pageispinned(oldpa));
		lock_acquire(global_paging_lock);
		swap_pagein(oldpa, swa);
		lpage_lock(oldlp);
		lock_release(global_paging_lock);
		/* Assert nobody else did the pagein. */
		KASSERT((oldlp->lp_paddr & PAGE_FRAME) == INVALID_PADDR);
		oldlp->lp_paddr = oldpa;
	}

	KASSERT(coremap_pageispinned(oldpa));

	coremap_copy_page(oldpa, newpa);

	KASSERT(LP_ISDIRTY(newlp));

	lpage_unlock(oldlp);
	lpage_unlock(newlp);

	coremap_unpin(newpa);
	coremap_unpin(oldpa);

	*lpret = newlp;
	return 0;
}