Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_swapout.c
Show First 20 Lines • Show All 550 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Bring the kernel stack for a specified thread back in. | * Bring the kernel stack for a specified thread back in. | ||||
*/ | */ | ||||
static void | static void | ||||
vm_thread_swapin(struct thread *td) | vm_thread_swapin(struct thread *td) | ||||
{ | { | ||||
vm_object_t ksobj; | vm_object_t ksobj; | ||||
vm_page_t ma[KSTACK_MAX_PAGES]; | vm_page_t ma[KSTACK_MAX_PAGES]; | ||||
int pages; | int a, count, i, j, pages, rv; | ||||
pages = td->td_kstack_pages; | pages = td->td_kstack_pages; | ||||
ksobj = td->td_kstack_obj; | ksobj = td->td_kstack_obj; | ||||
VM_OBJECT_WLOCK(ksobj); | VM_OBJECT_WLOCK(ksobj); | ||||
(void)vm_page_grab_pages(ksobj, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED, ma, | (void)vm_page_grab_pages(ksobj, 0, VM_ALLOC_NORMAL | VM_ALLOC_WIRED, ma, | ||||
pages); | pages); | ||||
for (int i = 0; i < pages;) { | for (i = 0; i < pages;) { | ||||
int j, a, count, rv; | |||||
vm_page_assert_xbusied(ma[i]); | vm_page_assert_xbusied(ma[i]); | ||||
if (ma[i]->valid == VM_PAGE_BITS_ALL) { | if (ma[i]->valid == VM_PAGE_BITS_ALL) { | ||||
vm_page_xunbusy(ma[i]); | vm_page_xunbusy(ma[i]); | ||||
i++; | i++; | ||||
continue; | continue; | ||||
} | } | ||||
vm_object_pip_add(ksobj, 1); | vm_object_pip_add(ksobj, 1); | ||||
for (j = i + 1; j < pages; j++) | for (j = i + 1; j < pages; j++) | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* This swapin algorithm attempts to swap-in processes only if there | * This swapin algorithm attempts to swap-in processes only if there | ||||
* is enough space for them. Of course, if a process waits for a long | * is enough space for them. Of course, if a process waits for a long | ||||
* time, it will be swapped in anyway. | * time, it will be swapped in anyway. | ||||
*/ | */ | ||||
void | void | ||||
swapper(void) | swapper(void) | ||||
{ | { | ||||
struct proc *p; | struct proc *p, *pp; | ||||
struct thread *td; | struct thread *td; | ||||
struct proc *pp; | int ppri, pri, slptime, swtime; | ||||
int slptime; | |||||
int swtime; | |||||
int ppri; | |||||
int pri; | |||||
loop: | loop: | ||||
if (vm_page_count_min()) { | if (vm_page_count_min()) { | ||||
VM_WAIT; | VM_WAIT; | ||||
goto loop; | goto loop; | ||||
} | } | ||||
pp = NULL; | pp = NULL; | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | |||||
* there are no sleeping or stopped processes, the longest-resident | * there are no sleeping or stopped processes, the longest-resident | ||||
* process is swapped out. | * process is swapped out. | ||||
*/ | */ | ||||
static void | static void | ||||
swapout_procs(int action) | swapout_procs(int action) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
struct thread *td; | struct thread *td; | ||||
int didswap = 0; | struct vmspace *vm; | ||||
int minslptime, slptime; | |||||
bool didswap; | |||||
minslptime = 100000; | |||||
didswap = false; | |||||
retry: | retry: | ||||
sx_slock(&allproc_lock); | sx_slock(&allproc_lock); | ||||
FOREACH_PROC_IN_SYSTEM(p) { | FOREACH_PROC_IN_SYSTEM(p) { | ||||
struct vmspace *vm; | |||||
int minslptime = 100000; | |||||
int slptime; | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
/* | /* | ||||
* Watch out for a process in | * Watch out for a process in | ||||
* creation. It may have no | * creation. It may have no | ||||
* address space or lock yet. | * address space or lock yet. | ||||
*/ | */ | ||||
if (p->p_state == PRS_NEW) { | if (p->p_state == PRS_NEW) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
Show All 33 Lines | if (!vm_map_trylock(&vm->vm_map)) | ||||
goto nextproc1; | goto nextproc1; | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
if (p->p_lock != 1 || (p->p_flag & (P_STOPPED_SINGLE | | if (p->p_lock != 1 || (p->p_flag & (P_STOPPED_SINGLE | | ||||
P_TRACED | P_SYSTEM)) != 0) | P_TRACED | P_SYSTEM)) != 0) | ||||
goto nextproc; | goto nextproc; | ||||
/* | /* | ||||
* only aiod changes vmspace, however it will be | * Only aiod changes vmspace. However, it will be | ||||
* skipped because of the if statement above checking | * skipped because of the if statement above checking | ||||
* for P_SYSTEM | * for P_SYSTEM. | ||||
*/ | */ | ||||
if ((p->p_flag & (P_INMEM|P_SWAPPINGOUT|P_SWAPPINGIN)) != P_INMEM) | if ((p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) != | ||||
P_INMEM) | |||||
goto nextproc; | goto nextproc; | ||||
switch (p->p_state) { | switch (p->p_state) { | ||||
default: | default: | ||||
/* Don't swap out processes in any sort | /* | ||||
* of 'special' state. */ | * Don't swap out processes in any sort | ||||
* of 'special' state. | |||||
*/ | |||||
break; | break; | ||||
case PRS_NORMAL: | case PRS_NORMAL: | ||||
/* | /* | ||||
* do not swapout a realtime process | * do not swapout a realtime process | ||||
* Check all the thread groups.. | * Check all the thread groups.. | ||||
*/ | */ | ||||
FOREACH_THREAD_IN_PROC(p, td) { | FOREACH_THREAD_IN_PROC(p, td) { | ||||
Show All 26 Lines | case PRS_NORMAL: | ||||
goto nextproc; | goto nextproc; | ||||
} | } | ||||
/* | /* | ||||
* If the system is under memory stress, | * If the system is under memory stress, | ||||
* or if we are swapping | * or if we are swapping | ||||
* idle processes >= swap_idle_threshold2, | * idle processes >= swap_idle_threshold2, | ||||
* then swap the process out. | * then swap the process out. | ||||
*/ | */ | ||||
if (((action & VM_SWAP_NORMAL) == 0) && | if ((action & VM_SWAP_NORMAL) == 0 && | ||||
(((action & VM_SWAP_IDLE) == 0) || | ((action & VM_SWAP_IDLE) == 0 || | ||||
(slptime < swap_idle_threshold2))) { | slptime < swap_idle_threshold2)) { | ||||
thread_unlock(td); | thread_unlock(td); | ||||
goto nextproc; | goto nextproc; | ||||
} | } | ||||
if (minslptime > slptime) | if (minslptime > slptime) | ||||
minslptime = slptime; | minslptime = slptime; | ||||
thread_unlock(td); | thread_unlock(td); | ||||
} | } | ||||
/* | /* | ||||
* If the pageout daemon didn't free enough pages, | * If the pageout daemon didn't free enough pages, | ||||
* or if this process is idle and the system is | * or if this process is idle and the system is | ||||
* configured to swap proactively, swap it out. | * configured to swap proactively, swap it out. | ||||
*/ | */ | ||||
if ((action & VM_SWAP_NORMAL) || | if ((action & VM_SWAP_NORMAL) != 0 || | ||||
((action & VM_SWAP_IDLE) && | ((action & VM_SWAP_IDLE) != 0 && | ||||
(minslptime > swap_idle_threshold2))) { | minslptime > swap_idle_threshold2)) { | ||||
_PRELE(p); | _PRELE(p); | ||||
if (swapout(p) == 0) | if (swapout(p) == 0) | ||||
didswap++; | didswap = true; | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
vm_map_unlock(&vm->vm_map); | vm_map_unlock(&vm->vm_map); | ||||
vmspace_free(vm); | vmspace_free(vm); | ||||
goto retry; | goto retry; | ||||
} | } | ||||
} | } | ||||
nextproc: | nextproc: | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | swapout(struct proc *p) | ||||
* The states of this process and its threads may have changed | * The states of this process and its threads may have changed | ||||
* by now. Assuming that there is only one pageout daemon thread, | * by now. Assuming that there is only one pageout daemon thread, | ||||
* this process should still be in memory. | * this process should still be in memory. | ||||
*/ | */ | ||||
KASSERT((p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) == | KASSERT((p->p_flag & (P_INMEM | P_SWAPPINGOUT | P_SWAPPINGIN)) == | ||||
P_INMEM, ("swapout: lost a swapout race?")); | P_INMEM, ("swapout: lost a swapout race?")); | ||||
/* | /* | ||||
* remember the process resident count | * Remember the resident count. | ||||
*/ | */ | ||||
p->p_vmspace->vm_swrss = vmspace_resident_count(p->p_vmspace); | p->p_vmspace->vm_swrss = vmspace_resident_count(p->p_vmspace); | ||||
/* | /* | ||||
* Check and mark all threads before we proceed. | * Check and mark all threads before we proceed. | ||||
*/ | */ | ||||
p->p_flag &= ~P_INMEM; | p->p_flag &= ~P_INMEM; | ||||
p->p_flag |= P_SWAPPINGOUT; | p->p_flag |= P_SWAPPINGOUT; | ||||
FOREACH_THREAD_IN_PROC(p, td) { | FOREACH_THREAD_IN_PROC(p, td) { | ||||
thread_lock(td); | thread_lock(td); | ||||
if (!thread_safetoswapout(td)) { | if (!thread_safetoswapout(td)) { | ||||
Show All 25 Lines |