Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_pageout.c
Show First 20 Lines • Show All 661 Lines • ▼ Show 20 Lines | for (object = first_object;; object = backing_object) { | ||||
/* | /* | ||||
* Scan the object's entire memory queue. | * Scan the object's entire memory queue. | ||||
*/ | */ | ||||
TAILQ_FOREACH(p, &object->memq, listq) { | TAILQ_FOREACH(p, &object->memq, listq) { | ||||
if (pmap_resident_count(pmap) <= desired) | if (pmap_resident_count(pmap) <= desired) | ||||
goto unlock_return; | goto unlock_return; | ||||
if (vm_page_busied(p)) | if (vm_page_busied(p)) | ||||
continue; | continue; | ||||
PCPU_INC(cnt.v_pdpages); | VM_CNT_INC(v_pdpages); | ||||
vm_page_lock(p); | vm_page_lock(p); | ||||
if (p->wire_count != 0 || p->hold_count != 0 || | if (p->wire_count != 0 || p->hold_count != 0 || | ||||
!pmap_page_exists_quick(pmap, p)) { | !pmap_page_exists_quick(pmap, p)) { | ||||
vm_page_unlock(p); | vm_page_unlock(p); | ||||
continue; | continue; | ||||
} | } | ||||
act_delta = pmap_ts_referenced(p); | act_delta = pmap_ts_referenced(p); | ||||
if ((p->aflags & PGA_REFERENCED) != 0) { | if ((p->aflags & PGA_REFERENCED) != 0) { | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | for (m = TAILQ_FIRST(&pq->pq_pl); | ||||
if (object->ref_count != 0) | if (object->ref_count != 0) | ||||
act_delta += pmap_ts_referenced(m); | act_delta += pmap_ts_referenced(m); | ||||
else { | else { | ||||
KASSERT(!pmap_page_is_mapped(m), | KASSERT(!pmap_page_is_mapped(m), | ||||
("page %p is mapped", m)); | ("page %p is mapped", m)); | ||||
} | } | ||||
if (act_delta != 0) { | if (act_delta != 0) { | ||||
if (object->ref_count != 0) { | if (object->ref_count != 0) { | ||||
PCPU_INC(cnt.v_reactivated); | VM_CNT_INC(v_reactivated); | ||||
vm_page_activate(m); | vm_page_activate(m); | ||||
/* | /* | ||||
* Increase the activation count if the page | * Increase the activation count if the page | ||||
* was referenced while in the laundry queue. | * was referenced while in the laundry queue. | ||||
* This makes it less likely that the page will | * This makes it less likely that the page will | ||||
* be returned prematurely to the inactive | * be returned prematurely to the inactive | ||||
* queue. | * queue. | ||||
Show All 32 Lines | for (m = TAILQ_FIRST(&pq->pq_pl); | ||||
* Clean pages are freed, and dirty pages are paged out unless | * Clean pages are freed, and dirty pages are paged out unless | ||||
* they belong to a dead object. Requeueing dirty pages from | * they belong to a dead object. Requeueing dirty pages from | ||||
* dead objects is pointless, as they are being paged out and | * dead objects is pointless, as they are being paged out and | ||||
* freed by the thread that destroyed the object. | * freed by the thread that destroyed the object. | ||||
*/ | */ | ||||
if (m->dirty == 0) { | if (m->dirty == 0) { | ||||
free_page: | free_page: | ||||
vm_page_free(m); | vm_page_free(m); | ||||
PCPU_INC(cnt.v_dfree); | VM_CNT_INC(v_dfree); | ||||
} else if ((object->flags & OBJ_DEAD) == 0) { | } else if ((object->flags & OBJ_DEAD) == 0) { | ||||
if (object->type != OBJT_SWAP && | if (object->type != OBJT_SWAP && | ||||
object->type != OBJT_DEFAULT) | object->type != OBJT_DEFAULT) | ||||
pageout_ok = true; | pageout_ok = true; | ||||
else if (disable_swap_pageouts) | else if (disable_swap_pageouts) | ||||
pageout_ok = false; | pageout_ok = false; | ||||
else | else | ||||
pageout_ok = true; | pageout_ok = true; | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | vm_pageout_laundry_worker(void *arg) | ||||
/* | /* | ||||
* The pageout laundry worker is never done, so loop forever. | * The pageout laundry worker is never done, so loop forever. | ||||
*/ | */ | ||||
for (;;) { | for (;;) { | ||||
KASSERT(target >= 0, ("negative target %d", target)); | KASSERT(target >= 0, ("negative target %d", target)); | ||||
KASSERT(shortfall_cycle >= 0, | KASSERT(shortfall_cycle >= 0, | ||||
("negative cycle %d", shortfall_cycle)); | ("negative cycle %d", shortfall_cycle)); | ||||
launder = 0; | launder = 0; | ||||
wakeups = VM_METER_PCPU_CNT(v_pdwakeups); | wakeups = VM_CNT_FETCH(v_pdwakeups); | ||||
/* | /* | ||||
* First determine whether we need to launder pages to meet a | * First determine whether we need to launder pages to meet a | ||||
* shortage of free pages. | * shortage of free pages. | ||||
*/ | */ | ||||
if (shortfall > 0) { | if (shortfall > 0) { | ||||
in_shortfall = true; | in_shortfall = true; | ||||
shortfall_cycle = VM_LAUNDER_RATE / VM_INACT_SCAN_RATE; | shortfall_cycle = VM_LAUNDER_RATE / VM_INACT_SCAN_RATE; | ||||
▲ Show 20 Lines • Show All 174 Lines • ▼ Show 20 Lines | vm_pageout_scan(struct vm_domain *vmd, int pass) | ||||
queue_locked = TRUE; | queue_locked = TRUE; | ||||
for (m = TAILQ_FIRST(&pq->pq_pl); | for (m = TAILQ_FIRST(&pq->pq_pl); | ||||
m != NULL && maxscan-- > 0 && page_shortage > 0; | m != NULL && maxscan-- > 0 && page_shortage > 0; | ||||
m = next) { | m = next) { | ||||
vm_pagequeue_assert_locked(pq); | vm_pagequeue_assert_locked(pq); | ||||
KASSERT(queue_locked, ("unlocked inactive queue")); | KASSERT(queue_locked, ("unlocked inactive queue")); | ||||
KASSERT(vm_page_inactive(m), ("Inactive queue %p", m)); | KASSERT(vm_page_inactive(m), ("Inactive queue %p", m)); | ||||
PCPU_INC(cnt.v_pdpages); | VM_CNT_INC(v_pdpages); | ||||
next = TAILQ_NEXT(m, plinks.q); | next = TAILQ_NEXT(m, plinks.q); | ||||
/* | /* | ||||
* skip marker pages | * skip marker pages | ||||
*/ | */ | ||||
if (m->flags & PG_MARKER) | if (m->flags & PG_MARKER) | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | unlock_page: | ||||
if (object->ref_count != 0) { | if (object->ref_count != 0) { | ||||
act_delta += pmap_ts_referenced(m); | act_delta += pmap_ts_referenced(m); | ||||
} else { | } else { | ||||
KASSERT(!pmap_page_is_mapped(m), | KASSERT(!pmap_page_is_mapped(m), | ||||
("vm_pageout_scan: page %p is mapped", m)); | ("vm_pageout_scan: page %p is mapped", m)); | ||||
} | } | ||||
if (act_delta != 0) { | if (act_delta != 0) { | ||||
if (object->ref_count != 0) { | if (object->ref_count != 0) { | ||||
PCPU_INC(cnt.v_reactivated); | VM_CNT_INC(v_reactivated); | ||||
vm_page_activate(m); | vm_page_activate(m); | ||||
/* | /* | ||||
* Increase the activation count if the page | * Increase the activation count if the page | ||||
* was referenced while in the inactive queue. | * was referenced while in the inactive queue. | ||||
* This makes it less likely that the page will | * This makes it less likely that the page will | ||||
* be returned prematurely to the inactive | * be returned prematurely to the inactive | ||||
* queue. | * queue. | ||||
Show All 28 Lines | unlock_page: | ||||
* to the laundry, unless they belong to a dead object. | * to the laundry, unless they belong to a dead object. | ||||
* Requeueing dirty pages from dead objects is pointless, as | * Requeueing dirty pages from dead objects is pointless, as | ||||
* they are being paged out and freed by the thread that | * they are being paged out and freed by the thread that | ||||
* destroyed the object. | * destroyed the object. | ||||
*/ | */ | ||||
if (m->dirty == 0) { | if (m->dirty == 0) { | ||||
free_page: | free_page: | ||||
vm_page_free(m); | vm_page_free(m); | ||||
PCPU_INC(cnt.v_dfree); | VM_CNT_INC(v_dfree); | ||||
--page_shortage; | --page_shortage; | ||||
} else if ((object->flags & OBJ_DEAD) == 0) | } else if ((object->flags & OBJ_DEAD) == 0) | ||||
vm_page_launder(m); | vm_page_launder(m); | ||||
drop_page: | drop_page: | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
if (!queue_locked) { | if (!queue_locked) { | ||||
vm_pagequeue_lock(pq); | vm_pagequeue_lock(pq); | ||||
Show All 13 Lines | drop_page: | ||||
*/ | */ | ||||
if (vm_laundry_request == VM_LAUNDRY_IDLE && | if (vm_laundry_request == VM_LAUNDRY_IDLE && | ||||
starting_page_shortage > 0) { | starting_page_shortage > 0) { | ||||
pq = &vm_dom[0].vmd_pagequeues[PQ_LAUNDRY]; | pq = &vm_dom[0].vmd_pagequeues[PQ_LAUNDRY]; | ||||
vm_pagequeue_lock(pq); | vm_pagequeue_lock(pq); | ||||
if (pq->pq_cnt > 0 || atomic_load_acq_int(&swapdev_enabled)) { | if (pq->pq_cnt > 0 || atomic_load_acq_int(&swapdev_enabled)) { | ||||
if (page_shortage > 0) { | if (page_shortage > 0) { | ||||
vm_laundry_request = VM_LAUNDRY_SHORTFALL; | vm_laundry_request = VM_LAUNDRY_SHORTFALL; | ||||
PCPU_INC(cnt.v_pdshortfalls); | VM_CNT_INC(v_pdshortfalls); | ||||
} else if (vm_laundry_request != VM_LAUNDRY_SHORTFALL) | } else if (vm_laundry_request != VM_LAUNDRY_SHORTFALL) | ||||
vm_laundry_request = VM_LAUNDRY_BACKGROUND; | vm_laundry_request = VM_LAUNDRY_BACKGROUND; | ||||
wakeup(&vm_laundry_request); | wakeup(&vm_laundry_request); | ||||
} | } | ||||
vm_pagequeue_unlock(pq); | vm_pagequeue_unlock(pq); | ||||
} | } | ||||
#if !defined(NO_SWAPPING) | #if !defined(NO_SWAPPING) | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | if (!vm_pageout_page_lock(m, &next)) { | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* The count for page daemon pages is updated after checking | * The count for page daemon pages is updated after checking | ||||
* the page for eligibility. | * the page for eligibility. | ||||
*/ | */ | ||||
PCPU_INC(cnt.v_pdpages); | VM_CNT_INC(v_pdpages); | ||||
/* | /* | ||||
* Check to see "how much" the page has been used. | * Check to see "how much" the page has been used. | ||||
*/ | */ | ||||
if ((m->aflags & PGA_REFERENCED) != 0) { | if ((m->aflags & PGA_REFERENCED) != 0) { | ||||
vm_page_aflag_clear(m, PGA_REFERENCED); | vm_page_aflag_clear(m, PGA_REFERENCED); | ||||
act_delta = 1; | act_delta = 1; | ||||
} else | } else | ||||
▲ Show 20 Lines • Show All 384 Lines • ▼ Show 20 Lines | while (TRUE) { | ||||
} else { | } else { | ||||
/* | /* | ||||
* Yes. Sleep until pages need to be reclaimed or | * Yes. Sleep until pages need to be reclaimed or | ||||
* have their reference stats updated. | * have their reference stats updated. | ||||
*/ | */ | ||||
if (mtx_sleep(&vm_pageout_wanted, | if (mtx_sleep(&vm_pageout_wanted, | ||||
&vm_page_queue_free_mtx, PDROP | PVM, "psleep", | &vm_page_queue_free_mtx, PDROP | PVM, "psleep", | ||||
hz) == 0) { | hz) == 0) { | ||||
PCPU_INC(cnt.v_pdwakeups); | VM_CNT_INC(v_pdwakeups); | ||||
pass = 1; | pass = 1; | ||||
} else | } else | ||||
pass = 0; | pass = 0; | ||||
} | } | ||||
target_met = vm_pageout_scan(domain, pass); | target_met = vm_pageout_scan(domain, pass); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 274 Lines • Show Last 20 Lines |