Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_pageout.c
Show First 20 Lines • Show All 1,738 Lines • ▼ Show 20 Lines | for (entry = map->header.next; entry != &map->header; | ||||
} | } | ||||
} | } | ||||
return (res); | return (res); | ||||
} | } | ||||
void | void | ||||
vm_pageout_oom(int shortage) | vm_pageout_oom(int shortage) | ||||
{ | { | ||||
VPS_ITERATOR_DECL(vps_iter); | |||||
struct proc *p, *bigproc; | struct proc *p, *bigproc; | ||||
vm_offset_t size, bigsize; | vm_offset_t size, bigsize; | ||||
struct thread *td; | struct thread *td; | ||||
struct vmspace *vm; | struct vmspace *vm; | ||||
bool breakout; | bool breakout; | ||||
/* | /* | ||||
* We keep the process bigproc locked once we find it to keep anyone | * We keep the process bigproc locked once we find it to keep anyone | ||||
* from messing with it; however, there is a possibility of | * from messing with it; however, there is a possibility of | ||||
* deadlock if process B is bigproc and one of its child processes | * deadlock if process B is bigproc and one of its child processes | ||||
* attempts to propagate a signal to B while we are waiting for A's | * attempts to propagate a signal to B while we are waiting for A's | ||||
* lock while walking this list. To avoid this, we don't block on | * lock while walking this list. To avoid this, we don't block on | ||||
* the process lock but just skip a process if it is already locked. | * the process lock but just skip a process if it is already locked. | ||||
*/ | */ | ||||
bigproc = NULL; | bigproc = NULL; | ||||
bigsize = 0; | bigsize = 0; | ||||
sx_slock(&allproc_lock); | |||||
VPS_LIST_RLOCK(); | |||||
VPS_FOREACH(vps_iter) { | |||||
CURVPS_SET(vps_iter); | |||||
sx_slock(&V_allproc_lock); | |||||
FOREACH_PROC_IN_SYSTEM(p) { | FOREACH_PROC_IN_SYSTEM(p) { | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
/* | /* | ||||
* If this is a system, protected or killed process, skip it. | * If this is a system, protected or killed process, | ||||
* skip it. | |||||
*/ | */ | ||||
if (p->p_state != PRS_NORMAL || (p->p_flag & (P_INEXEC | | if (p->p_state != PRS_NORMAL || (p->p_flag & (P_INEXEC | | ||||
P_PROTECTED | P_SYSTEM | P_WEXIT)) != 0 || | P_PROTECTED | P_SYSTEM | P_WEXIT)) != 0 || | ||||
p->p_pid == 1 || P_KILLED(p) || | p->p_pid == 1 || P_KILLED(p) || | ||||
(p->p_pid < 48 && swap_pager_avail != 0)) { | (p->p_pid < 48 && swap_pager_avail != 0)) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* If the process is in a non-running type state, | * If the process is in a non-running type state, | ||||
* don't touch it. Check all the threads individually. | * don't touch it. Check all the threads individually. | ||||
*/ | */ | ||||
breakout = false; | breakout = false; | ||||
FOREACH_THREAD_IN_PROC(p, td) { | FOREACH_THREAD_IN_PROC(p, td) { | ||||
thread_lock(td); | thread_lock(td); | ||||
if (!TD_ON_RUNQ(td) && | if (!TD_ON_RUNQ(td) && | ||||
!TD_IS_RUNNING(td) && | !TD_IS_RUNNING(td) && | ||||
!TD_IS_SLEEPING(td) && | !TD_IS_SLEEPING(td) && | ||||
!TD_IS_SUSPENDED(td) && | !TD_IS_SUSPENDED(td) && | ||||
!TD_IS_SWAPPED(td)) { | !TD_IS_SWAPPED(td)) { | ||||
thread_unlock(td); | thread_unlock(td); | ||||
breakout = true; | breakout = true; | ||||
break; | break; | ||||
} | } | ||||
thread_unlock(td); | thread_unlock(td); | ||||
} | } | ||||
if (breakout) { | if (breakout) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* get the process size | * get the process size | ||||
*/ | */ | ||||
vm = vmspace_acquire_ref(p); | vm = vmspace_acquire_ref(p); | ||||
if (vm == NULL) { | if (vm == NULL) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
continue; | continue; | ||||
} | } | ||||
_PHOLD_LITE(p); | _PHOLD_LITE(p); | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&V_allproc_lock); | ||||
if (!vm_map_trylock_read(&vm->vm_map)) { | if (!vm_map_trylock_read(&vm->vm_map)) { | ||||
vmspace_free(vm); | vmspace_free(vm); | ||||
sx_slock(&allproc_lock); | sx_slock(&V_allproc_lock); | ||||
PRELE(p); | PRELE(p); | ||||
continue; | continue; | ||||
} | } | ||||
size = vmspace_swap_count(vm); | size = vmspace_swap_count(vm); | ||||
if (shortage == VM_OOM_MEM) | if (shortage == VM_OOM_MEM) | ||||
size += vm_pageout_oom_pagecount(vm); | size += vm_pageout_oom_pagecount(vm); | ||||
vm_map_unlock_read(&vm->vm_map); | vm_map_unlock_read(&vm->vm_map); | ||||
vmspace_free(vm); | vmspace_free(vm); | ||||
sx_slock(&allproc_lock); | sx_slock(&V_allproc_lock); | ||||
/* | /* | ||||
* If this process is bigger than the biggest one, | * If this process is bigger than the biggest one, | ||||
* remember it. | * remember it. | ||||
*/ | */ | ||||
if (size > bigsize) { | if (size > bigsize) { | ||||
if (bigproc != NULL) | if (bigproc != NULL) | ||||
PRELE(bigproc); | PRELE(bigproc); | ||||
bigproc = p; | bigproc = p; | ||||
bigsize = size; | bigsize = size; | ||||
} else { | } else { | ||||
PRELE(p); | PRELE(p); | ||||
} | } | ||||
} | } | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&V_allproc_lock); | ||||
CURVPS_RESTORE(); | |||||
} | |||||
VPS_LIST_RUNLOCK(); | |||||
if (bigproc != NULL) { | if (bigproc != NULL) { | ||||
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); | ||||
▲ Show 20 Lines • Show All 258 Lines • Show Last 20 Lines |