Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_pageout.c
Show First 20 Lines • Show All 1,744 Lines • ▼ Show 20 Lines | if (size > bigsize) { | ||||
bigproc = p; | bigproc = p; | ||||
bigsize = size; | bigsize = size; | ||||
} else { | } else { | ||||
PRELE(p); | PRELE(p); | ||||
} | } | ||||
} | } | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&allproc_lock); | ||||
if (bigproc != NULL) { | if (bigproc != NULL) { | ||||
int i; | |||||
if (vm_panic_on_oom != 0) | if (vm_panic_on_oom != 0) | ||||
panic("out of swap space"); | panic("out of swap space"); | ||||
PROC_LOCK(bigproc); | PROC_LOCK(bigproc); | ||||
killproc(bigproc, "out of swap space"); | killproc(bigproc, "out of swap space"); | ||||
sched_nice(bigproc, PRIO_MIN); | sched_nice(bigproc, PRIO_MIN); | ||||
_PRELE(bigproc); | _PRELE(bigproc); | ||||
PROC_UNLOCK(bigproc); | PROC_UNLOCK(bigproc); | ||||
for (i = 0; i < vm_ndomains; i++) | |||||
wakeup(&VM_DOMAIN(i)->vmd_free_count); | |||||
} | } | ||||
} | } | ||||
static void | static void | ||||
vm_pageout_worker(void *arg) | vm_pageout_worker(void *arg) | ||||
{ | { | ||||
struct vm_domain *vmd; | struct vm_domain *vmd; | ||||
int domain, pass; | int domain, pass; | ||||
Show All 19 Lines | vm_pageout_worker(void *arg) | ||||
/* | /* | ||||
* The pageout daemon worker is never done, so loop forever. | * The pageout daemon worker is never done, so loop forever. | ||||
*/ | */ | ||||
while (TRUE) { | while (TRUE) { | ||||
vm_domain_free_lock(vmd); | vm_domain_free_lock(vmd); | ||||
/* | /* | ||||
* Generally, after a level >= 1 scan, if there are enough | |||||
* free pages to wakeup the waiters, then they are already | |||||
* awake. A call to vm_page_free() during the scan awakened | |||||
* them. However, in the following case, this wakeup serves | |||||
* to bound the amount of time that a thread might wait. | |||||
* Suppose a thread's call to vm_page_alloc() fails, but | |||||
* before that thread calls VM_WAIT, enough pages are freed by | |||||
* other threads to alleviate the free page shortage. The | |||||
* thread will, nonetheless, wait until another page is freed | |||||
* or this wakeup is performed. | |||||
*/ | |||||
if (vmd->vmd_pages_needed && !vm_paging_min(vmd)) { | |||||
vmd->vmd_pages_needed = false; | |||||
wakeup(&vmd->vmd_free_count); | |||||
} | |||||
/* | |||||
* Do not clear vmd_pageout_wanted until we reach our free page | * Do not clear vmd_pageout_wanted until we reach our free page | ||||
* target. Otherwise, we may be awakened over and over again, | * target. Otherwise, we may be awakened over and over again, | ||||
* wasting CPU time. | * wasting CPU time. | ||||
*/ | */ | ||||
if (vmd->vmd_pageout_wanted && target_met) | if (vmd->vmd_pageout_wanted && target_met) | ||||
vmd->vmd_pageout_wanted = false; | vmd->vmd_pageout_wanted = false; | ||||
/* | /* | ||||
Show All 11 Lines | if (vmd->vmd_pageout_wanted) { | ||||
* try again later. | * try again later. | ||||
*/ | */ | ||||
vm_domain_free_unlock(vmd); | vm_domain_free_unlock(vmd); | ||||
if (pass >= 1) | if (pass >= 1) | ||||
pause("pwait", hz / VM_INACT_SCAN_RATE); | pause("pwait", hz / VM_INACT_SCAN_RATE); | ||||
pass++; | pass++; | ||||
} else { | } else { | ||||
/* | /* | ||||
* Yes. If threads are still sleeping in VM_WAIT | * Yes. If threads are still sleeping in vm_wait() | ||||
* then we immediately start a new scan. Otherwise, | * then we immediately start a new scan. Otherwise, | ||||
* sleep until the next wakeup or until pages need to | * sleep until the next wakeup or until pages need to | ||||
* have their reference stats updated. | * have their reference stats updated. | ||||
*/ | */ | ||||
if (vmd->vmd_pages_needed) { | if (mtx_sleep(&vmd->vmd_pageout_wanted, | ||||
vm_domain_free_unlock(vmd); | |||||
if (pass == 0) | |||||
pass++; | |||||
} else if (mtx_sleep(&vmd->vmd_pageout_wanted, | |||||
vm_domain_free_lockptr(vmd), PDROP | PVM, | vm_domain_free_lockptr(vmd), PDROP | PVM, | ||||
"psleep", hz) == 0) { | "psleep", hz) == 0) { | ||||
VM_CNT_INC(v_pdwakeups); | VM_CNT_INC(v_pdwakeups); | ||||
pass = 1; | pass = 1; | ||||
} else | } else | ||||
pass = 0; | pass = 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | pagedaemon_wakeup(int domain) | ||||
vmd = VM_DOMAIN(domain); | vmd = VM_DOMAIN(domain); | ||||
vm_domain_free_assert_unlocked(vmd); | vm_domain_free_assert_unlocked(vmd); | ||||
if (!vmd->vmd_pageout_wanted && curthread->td_proc != pageproc) { | if (!vmd->vmd_pageout_wanted && curthread->td_proc != pageproc) { | ||||
vmd->vmd_pageout_wanted = true; | vmd->vmd_pageout_wanted = true; | ||||
wakeup(&vmd->vmd_pageout_wanted); | wakeup(&vmd->vmd_pageout_wanted); | ||||
} | } | ||||
} | |||||
/* | |||||
* Wake up the page daemon and wait for it to reclaim free pages. | |||||
* | |||||
* This function returns with the free queues mutex unlocked. | |||||
*/ | |||||
void | |||||
pagedaemon_wait(int domain, int pri, const char *wmesg) | |||||
{ | |||||
struct vm_domain *vmd; | |||||
vmd = VM_DOMAIN(domain); | |||||
vm_domain_free_assert_locked(vmd); | |||||
/* | |||||
* vmd_pageout_wanted may have been set by an advisory wakeup, but if | |||||
* the page daemon is running on a CPU, the wakeup will have been lost. | |||||
* Thus, deliver a potentially spurious wakeup to ensure that the page | |||||
* daemon has been notified of the shortage. | |||||
*/ | |||||
if (!vmd->vmd_pageout_wanted || !vmd->vmd_pages_needed) { | |||||
vmd->vmd_pageout_wanted = true; | |||||
wakeup(&vmd->vmd_pageout_wanted); | |||||
} | |||||
vmd->vmd_pages_needed = true; | |||||
vmd->vmd_waiters++; | |||||
msleep(&vmd->vmd_free_count, vm_domain_free_lockptr(vmd), PDROP | pri, | |||||
wmesg, 0); | |||||
vmd->vmd_waiters--; | |||||
} | } |