1ac04195bSKonstantin Belousov /*- 2796df753SPedro F. Giffuni * SPDX-License-Identifier: (BSD-4-Clause AND MIT-CMU) 3796df753SPedro F. Giffuni * 4ac04195bSKonstantin Belousov * Copyright (c) 1991 Regents of the University of California. 5ac04195bSKonstantin Belousov * All rights reserved. 6ac04195bSKonstantin Belousov * Copyright (c) 1994 John S. Dyson 7ac04195bSKonstantin Belousov * All rights reserved. 8ac04195bSKonstantin Belousov * Copyright (c) 1994 David Greenman 9ac04195bSKonstantin Belousov * All rights reserved. 10ac04195bSKonstantin Belousov * Copyright (c) 2005 Yahoo! Technologies Norway AS 11ac04195bSKonstantin Belousov * All rights reserved. 12ac04195bSKonstantin Belousov * 13ac04195bSKonstantin Belousov * This code is derived from software contributed to Berkeley by 14ac04195bSKonstantin Belousov * The Mach Operating System project at Carnegie-Mellon University. 15ac04195bSKonstantin Belousov * 16ac04195bSKonstantin Belousov * Redistribution and use in source and binary forms, with or without 17ac04195bSKonstantin Belousov * modification, are permitted provided that the following conditions 18ac04195bSKonstantin Belousov * are met: 19ac04195bSKonstantin Belousov * 1. Redistributions of source code must retain the above copyright 20ac04195bSKonstantin Belousov * notice, this list of conditions and the following disclaimer. 21ac04195bSKonstantin Belousov * 2. Redistributions in binary form must reproduce the above copyright 22ac04195bSKonstantin Belousov * notice, this list of conditions and the following disclaimer in the 23ac04195bSKonstantin Belousov * documentation and/or other materials provided with the distribution. 24ac04195bSKonstantin Belousov * 3. All advertising materials mentioning features or use of this software 25ac04195bSKonstantin Belousov * must display the following acknowledgement: 26ac04195bSKonstantin Belousov * This product includes software developed by the University of 27ac04195bSKonstantin Belousov * California, Berkeley and its contributors. 28ac04195bSKonstantin Belousov * 4. Neither the name of the University nor the names of its contributors 29ac04195bSKonstantin Belousov * may be used to endorse or promote products derived from this software 30ac04195bSKonstantin Belousov * without specific prior written permission. 31ac04195bSKonstantin Belousov * 32ac04195bSKonstantin Belousov * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33ac04195bSKonstantin Belousov * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34ac04195bSKonstantin Belousov * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35ac04195bSKonstantin Belousov * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36ac04195bSKonstantin Belousov * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37ac04195bSKonstantin Belousov * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38ac04195bSKonstantin Belousov * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39ac04195bSKonstantin Belousov * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40ac04195bSKonstantin Belousov * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41ac04195bSKonstantin Belousov * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42ac04195bSKonstantin Belousov * SUCH DAMAGE. 43ac04195bSKonstantin Belousov * 44ac04195bSKonstantin Belousov * 45ac04195bSKonstantin Belousov * Copyright (c) 1987, 1990 Carnegie-Mellon University. 46ac04195bSKonstantin Belousov * All rights reserved. 47ac04195bSKonstantin Belousov * 48ac04195bSKonstantin Belousov * Authors: Avadis Tevanian, Jr., Michael Wayne Young 49ac04195bSKonstantin Belousov * 50ac04195bSKonstantin Belousov * Permission to use, copy, modify and distribute this software and 51ac04195bSKonstantin Belousov * its documentation is hereby granted, provided that both the copyright 52ac04195bSKonstantin Belousov * notice and this permission notice appear in all copies of the 53ac04195bSKonstantin Belousov * software, derivative works or modified versions, and any portions 54ac04195bSKonstantin Belousov * thereof, and that both notices appear in supporting documentation. 55ac04195bSKonstantin Belousov * 56ac04195bSKonstantin Belousov * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 57ac04195bSKonstantin Belousov * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 58ac04195bSKonstantin Belousov * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 59ac04195bSKonstantin Belousov * 60ac04195bSKonstantin Belousov * Carnegie Mellon requests users of this software to return to 61ac04195bSKonstantin Belousov * 62ac04195bSKonstantin Belousov * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 63ac04195bSKonstantin Belousov * School of Computer Science 64ac04195bSKonstantin Belousov * Carnegie Mellon University 65ac04195bSKonstantin Belousov * Pittsburgh PA 15213-3890 66ac04195bSKonstantin Belousov * 67ac04195bSKonstantin Belousov * any improvements or extensions that they make and grant Carnegie the 68ac04195bSKonstantin Belousov * rights to redistribute these changes. 69ac04195bSKonstantin Belousov */ 70ac04195bSKonstantin Belousov 71ac04195bSKonstantin Belousov #include "opt_kstack_pages.h" 72ac04195bSKonstantin Belousov #include "opt_kstack_max_pages.h" 73ac04195bSKonstantin Belousov #include "opt_vm.h" 74ac04195bSKonstantin Belousov 75ac04195bSKonstantin Belousov #include <sys/param.h> 76ac04195bSKonstantin Belousov #include <sys/systm.h> 77ac04195bSKonstantin Belousov #include <sys/limits.h> 78ac04195bSKonstantin Belousov #include <sys/kernel.h> 79ac04195bSKonstantin Belousov #include <sys/eventhandler.h> 80ac04195bSKonstantin Belousov #include <sys/lock.h> 81ac04195bSKonstantin Belousov #include <sys/mutex.h> 82ac04195bSKonstantin Belousov #include <sys/proc.h> 83ac04195bSKonstantin Belousov #include <sys/kthread.h> 84ac04195bSKonstantin Belousov #include <sys/ktr.h> 85ac04195bSKonstantin Belousov #include <sys/mount.h> 86ac04195bSKonstantin Belousov #include <sys/racct.h> 87ac04195bSKonstantin Belousov #include <sys/resourcevar.h> 8811b57401SHans Petter Selasky #include <sys/refcount.h> 89ac04195bSKonstantin Belousov #include <sys/sched.h> 90ac04195bSKonstantin Belousov #include <sys/sdt.h> 91ac04195bSKonstantin Belousov #include <sys/signalvar.h> 92ac04195bSKonstantin Belousov #include <sys/smp.h> 93ac04195bSKonstantin Belousov #include <sys/time.h> 94ac04195bSKonstantin Belousov #include <sys/vnode.h> 95ac04195bSKonstantin Belousov #include <sys/vmmeter.h> 96ac04195bSKonstantin Belousov #include <sys/rwlock.h> 97ac04195bSKonstantin Belousov #include <sys/sx.h> 98ac04195bSKonstantin Belousov #include <sys/sysctl.h> 99ac04195bSKonstantin Belousov 100ac04195bSKonstantin Belousov #include <vm/vm.h> 101ac04195bSKonstantin Belousov #include <vm/vm_param.h> 102f13fa9dfSMark Johnston #include <vm/vm_kern.h> 103ac04195bSKonstantin Belousov #include <vm/vm_object.h> 104ac04195bSKonstantin Belousov #include <vm/vm_page.h> 105ac04195bSKonstantin Belousov #include <vm/vm_map.h> 106ac04195bSKonstantin Belousov #include <vm/vm_pageout.h> 10741fd4b94SMark Johnston #include <vm/vm_pager.h> 108e8bcf696SMark Johnston #include <vm/vm_phys.h> 109ac04195bSKonstantin Belousov #include <vm/swap_pager.h> 110ac04195bSKonstantin Belousov #include <vm/vm_extern.h> 111ac04195bSKonstantin Belousov #include <vm/uma.h> 112ac04195bSKonstantin Belousov 113ac04195bSKonstantin Belousov /* the kernel process "vm_daemon" */ 114ac04195bSKonstantin Belousov static void vm_daemon(void); 115ac04195bSKonstantin Belousov static struct proc *vmproc; 116ac04195bSKonstantin Belousov 117ac04195bSKonstantin Belousov static struct kproc_desc vm_kp = { 118ac04195bSKonstantin Belousov "vmdaemon", 119ac04195bSKonstantin Belousov vm_daemon, 120ac04195bSKonstantin Belousov &vmproc 121ac04195bSKonstantin Belousov }; 122ac04195bSKonstantin Belousov SYSINIT(vmdaemon, SI_SUB_KTHREAD_VM, SI_ORDER_FIRST, kproc_start, &vm_kp); 123ac04195bSKonstantin Belousov 1240f559a9fSEdward Tomasz Napierala static int vm_daemon_timeout = 0; 1250f559a9fSEdward Tomasz Napierala SYSCTL_INT(_vm, OID_AUTO, vmdaemon_timeout, CTLFLAG_RW, 1260f559a9fSEdward Tomasz Napierala &vm_daemon_timeout, 0, 1270f559a9fSEdward Tomasz Napierala "Time between vmdaemon runs"); 1280f559a9fSEdward Tomasz Napierala 129ac04195bSKonstantin Belousov static int vm_daemon_needed; 130ac04195bSKonstantin Belousov static struct mtx vm_daemon_mtx; 131ac04195bSKonstantin Belousov /* Allow for use by vm_pageout before vm_daemon is initialized. */ 132ac04195bSKonstantin Belousov MTX_SYSINIT(vm_daemon, &vm_daemon_mtx, "vm daemon", MTX_DEF); 133ac04195bSKonstantin Belousov 134ac04195bSKonstantin Belousov static void vm_swapout_map_deactivate_pages(vm_map_t, long); 1359be9ea42SMark Johnston static void vm_swapout_object_deactivate(pmap_t, vm_object_t, long); 136ac04195bSKonstantin Belousov 1379be9ea42SMark Johnston static void 1389be9ea42SMark Johnston vm_swapout_object_deactivate_page(pmap_t pmap, vm_page_t m, bool unmap) 1399be9ea42SMark Johnston { 1409be9ea42SMark Johnston 141ac04195bSKonstantin Belousov /* 1423c01c56bSMark Johnston * Ignore unreclaimable wired pages. Repeat the check after busying 1433c01c56bSMark Johnston * since a busy holder may wire the page. 1449be9ea42SMark Johnston */ 1453c01c56bSMark Johnston if (vm_page_wired(m) || !vm_page_tryxbusy(m)) 1463c01c56bSMark Johnston return; 1473c01c56bSMark Johnston 1489be9ea42SMark Johnston if (vm_page_wired(m) || !pmap_page_exists_quick(pmap, m)) { 1499be9ea42SMark Johnston vm_page_xunbusy(m); 1509be9ea42SMark Johnston return; 1519be9ea42SMark Johnston } 1523c01c56bSMark Johnston if (!pmap_is_referenced(m)) { 1533c01c56bSMark Johnston if (!vm_page_active(m)) 1549be9ea42SMark Johnston (void)vm_page_try_remove_all(m); 1553c01c56bSMark Johnston else if (unmap && vm_page_try_remove_all(m)) 1569be9ea42SMark Johnston vm_page_deactivate(m); 1573c01c56bSMark Johnston } 1589be9ea42SMark Johnston vm_page_xunbusy(m); 1599be9ea42SMark Johnston } 1609be9ea42SMark Johnston 1619be9ea42SMark Johnston /* 1629be9ea42SMark Johnston * vm_swapout_object_deactivate 163ac04195bSKonstantin Belousov * 164ac04195bSKonstantin Belousov * Deactivate enough pages to satisfy the inactive target 165ac04195bSKonstantin Belousov * requirements. 166ac04195bSKonstantin Belousov * 167ac04195bSKonstantin Belousov * The object and map must be locked. 168ac04195bSKonstantin Belousov */ 169ac04195bSKonstantin Belousov static void 1709be9ea42SMark Johnston vm_swapout_object_deactivate(pmap_t pmap, vm_object_t first_object, 171ac04195bSKonstantin Belousov long desired) 172ac04195bSKonstantin Belousov { 173ac04195bSKonstantin Belousov vm_object_t backing_object, object; 1749be9ea42SMark Johnston vm_page_t m; 1759be9ea42SMark Johnston bool unmap; 176ac04195bSKonstantin Belousov 177ac04195bSKonstantin Belousov VM_OBJECT_ASSERT_LOCKED(first_object); 178ac04195bSKonstantin Belousov if ((first_object->flags & OBJ_FICTITIOUS) != 0) 179ac04195bSKonstantin Belousov return; 180ac04195bSKonstantin Belousov for (object = first_object;; object = backing_object) { 181ac04195bSKonstantin Belousov if (pmap_resident_count(pmap) <= desired) 182ac04195bSKonstantin Belousov goto unlock_return; 183ac04195bSKonstantin Belousov VM_OBJECT_ASSERT_LOCKED(object); 184ac04195bSKonstantin Belousov if ((object->flags & OBJ_UNMANAGED) != 0 || 185c99d0c58SMark Johnston blockcount_read(&object->paging_in_progress) > 0) 186ac04195bSKonstantin Belousov goto unlock_return; 187ac04195bSKonstantin Belousov 1889be9ea42SMark Johnston unmap = true; 189ac04195bSKonstantin Belousov if (object->shadow_count > 1) 1909be9ea42SMark Johnston unmap = false; 1919be9ea42SMark Johnston 192ac04195bSKonstantin Belousov /* 193ac04195bSKonstantin Belousov * Scan the object's entire memory queue. 194ac04195bSKonstantin Belousov */ 1959be9ea42SMark Johnston TAILQ_FOREACH(m, &object->memq, listq) { 196ac04195bSKonstantin Belousov if (pmap_resident_count(pmap) <= desired) 197ac04195bSKonstantin Belousov goto unlock_return; 1989997c048SKonstantin Belousov if (should_yield()) 1999997c048SKonstantin Belousov goto unlock_return; 2009be9ea42SMark Johnston vm_swapout_object_deactivate_page(pmap, m, unmap); 201ac04195bSKonstantin Belousov } 202ac04195bSKonstantin Belousov if ((backing_object = object->backing_object) == NULL) 203ac04195bSKonstantin Belousov goto unlock_return; 204ac04195bSKonstantin Belousov VM_OBJECT_RLOCK(backing_object); 205ac04195bSKonstantin Belousov if (object != first_object) 206ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(object); 207ac04195bSKonstantin Belousov } 208ac04195bSKonstantin Belousov unlock_return: 209ac04195bSKonstantin Belousov if (object != first_object) 210ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(object); 211ac04195bSKonstantin Belousov } 212ac04195bSKonstantin Belousov 213ac04195bSKonstantin Belousov /* 214ac04195bSKonstantin Belousov * deactivate some number of pages in a map, try to do it fairly, but 215ac04195bSKonstantin Belousov * that is really hard to do. 216ac04195bSKonstantin Belousov */ 217ac04195bSKonstantin Belousov static void 218ac04195bSKonstantin Belousov vm_swapout_map_deactivate_pages(vm_map_t map, long desired) 219ac04195bSKonstantin Belousov { 220ac04195bSKonstantin Belousov vm_map_entry_t tmpe; 221ac04195bSKonstantin Belousov vm_object_t obj, bigobj; 222ac04195bSKonstantin Belousov int nothingwired; 223ac04195bSKonstantin Belousov 2240080a8faSKonstantin Belousov if (!vm_map_trylock_read(map)) 225ac04195bSKonstantin Belousov return; 226ac04195bSKonstantin Belousov 227ac04195bSKonstantin Belousov bigobj = NULL; 228ac04195bSKonstantin Belousov nothingwired = TRUE; 229ac04195bSKonstantin Belousov 230ac04195bSKonstantin Belousov /* 231ac04195bSKonstantin Belousov * first, search out the biggest object, and try to free pages from 232ac04195bSKonstantin Belousov * that. 233ac04195bSKonstantin Belousov */ 2342288078cSDoug Moore VM_MAP_ENTRY_FOREACH(tmpe, map) { 235ac04195bSKonstantin Belousov if ((tmpe->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { 236ac04195bSKonstantin Belousov obj = tmpe->object.vm_object; 237ac04195bSKonstantin Belousov if (obj != NULL && VM_OBJECT_TRYRLOCK(obj)) { 238ac04195bSKonstantin Belousov if (obj->shadow_count <= 1 && 239ac04195bSKonstantin Belousov (bigobj == NULL || 240ac04195bSKonstantin Belousov bigobj->resident_page_count < 241ac04195bSKonstantin Belousov obj->resident_page_count)) { 242ac04195bSKonstantin Belousov if (bigobj != NULL) 243ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(bigobj); 244ac04195bSKonstantin Belousov bigobj = obj; 245ac04195bSKonstantin Belousov } else 246ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(obj); 247ac04195bSKonstantin Belousov } 248ac04195bSKonstantin Belousov } 249ac04195bSKonstantin Belousov if (tmpe->wired_count > 0) 250ac04195bSKonstantin Belousov nothingwired = FALSE; 251ac04195bSKonstantin Belousov } 252ac04195bSKonstantin Belousov 253ac04195bSKonstantin Belousov if (bigobj != NULL) { 2549be9ea42SMark Johnston vm_swapout_object_deactivate(map->pmap, bigobj, desired); 255ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(bigobj); 256ac04195bSKonstantin Belousov } 257ac04195bSKonstantin Belousov /* 258ac04195bSKonstantin Belousov * Next, hunt around for other pages to deactivate. We actually 259ac04195bSKonstantin Belousov * do this search sort of wrong -- .text first is not the best idea. 260ac04195bSKonstantin Belousov */ 2612288078cSDoug Moore VM_MAP_ENTRY_FOREACH(tmpe, map) { 262ac04195bSKonstantin Belousov if (pmap_resident_count(vm_map_pmap(map)) <= desired) 263ac04195bSKonstantin Belousov break; 264ac04195bSKonstantin Belousov if ((tmpe->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { 265ac04195bSKonstantin Belousov obj = tmpe->object.vm_object; 266ac04195bSKonstantin Belousov if (obj != NULL) { 267ac04195bSKonstantin Belousov VM_OBJECT_RLOCK(obj); 2689be9ea42SMark Johnston vm_swapout_object_deactivate(map->pmap, obj, 2699be9ea42SMark Johnston desired); 270ac04195bSKonstantin Belousov VM_OBJECT_RUNLOCK(obj); 271ac04195bSKonstantin Belousov } 272ac04195bSKonstantin Belousov } 273ac04195bSKonstantin Belousov } 274ac04195bSKonstantin Belousov 275ac04195bSKonstantin Belousov /* 276ac04195bSKonstantin Belousov * Remove all mappings if a process is swapped out, this will free page 277ac04195bSKonstantin Belousov * table pages. 278ac04195bSKonstantin Belousov */ 279ac04195bSKonstantin Belousov if (desired == 0 && nothingwired) { 280ac04195bSKonstantin Belousov pmap_remove(vm_map_pmap(map), vm_map_min(map), 281ac04195bSKonstantin Belousov vm_map_max(map)); 282ac04195bSKonstantin Belousov } 283ac04195bSKonstantin Belousov 2840080a8faSKonstantin Belousov vm_map_unlock_read(map); 285ac04195bSKonstantin Belousov } 286ac04195bSKonstantin Belousov 287ac04195bSKonstantin Belousov static void 288ac04195bSKonstantin Belousov vm_daemon(void) 289ac04195bSKonstantin Belousov { 290ac04195bSKonstantin Belousov struct rlimit rsslim; 291ac04195bSKonstantin Belousov struct proc *p; 292ac04195bSKonstantin Belousov struct thread *td; 293ac04195bSKonstantin Belousov struct vmspace *vm; 29413a1129dSMark Johnston int breakout, tryagain, attempts; 295ac04195bSKonstantin Belousov uint64_t rsize, ravailable; 2960f559a9fSEdward Tomasz Napierala 2970f559a9fSEdward Tomasz Napierala if (racct_enable && vm_daemon_timeout == 0) 2980f559a9fSEdward Tomasz Napierala vm_daemon_timeout = hz; 299ac04195bSKonstantin Belousov 300ac04195bSKonstantin Belousov while (TRUE) { 301ac04195bSKonstantin Belousov mtx_lock(&vm_daemon_mtx); 302ac04195bSKonstantin Belousov msleep(&vm_daemon_needed, &vm_daemon_mtx, PPAUSE, "psleep", 3030f559a9fSEdward Tomasz Napierala vm_daemon_timeout); 304ac04195bSKonstantin Belousov mtx_unlock(&vm_daemon_mtx); 305ac04195bSKonstantin Belousov 306ac04195bSKonstantin Belousov /* 307ac04195bSKonstantin Belousov * scan the processes for exceeding their rlimits or if 308ac04195bSKonstantin Belousov * process is swapped out -- deactivate pages 309ac04195bSKonstantin Belousov */ 310ac04195bSKonstantin Belousov tryagain = 0; 311ac04195bSKonstantin Belousov attempts = 0; 312ac04195bSKonstantin Belousov again: 313ac04195bSKonstantin Belousov attempts++; 314ac04195bSKonstantin Belousov sx_slock(&allproc_lock); 315ac04195bSKonstantin Belousov FOREACH_PROC_IN_SYSTEM(p) { 316ac04195bSKonstantin Belousov vm_pindex_t limit, size; 317ac04195bSKonstantin Belousov 318ac04195bSKonstantin Belousov /* 319ac04195bSKonstantin Belousov * if this is a system process or if we have already 320ac04195bSKonstantin Belousov * looked at this process, skip it. 321ac04195bSKonstantin Belousov */ 322ac04195bSKonstantin Belousov PROC_LOCK(p); 323ac04195bSKonstantin Belousov if (p->p_state != PRS_NORMAL || 324ac04195bSKonstantin Belousov p->p_flag & (P_INEXEC | P_SYSTEM | P_WEXIT)) { 325ac04195bSKonstantin Belousov PROC_UNLOCK(p); 326ac04195bSKonstantin Belousov continue; 327ac04195bSKonstantin Belousov } 328ac04195bSKonstantin Belousov /* 329ac04195bSKonstantin Belousov * if the process is in a non-running type state, 330ac04195bSKonstantin Belousov * don't touch it. 331ac04195bSKonstantin Belousov */ 332ac04195bSKonstantin Belousov breakout = 0; 333ac04195bSKonstantin Belousov FOREACH_THREAD_IN_PROC(p, td) { 334ac04195bSKonstantin Belousov thread_lock(td); 335ac04195bSKonstantin Belousov if (!TD_ON_RUNQ(td) && 336ac04195bSKonstantin Belousov !TD_IS_RUNNING(td) && 337ac04195bSKonstantin Belousov !TD_IS_SLEEPING(td) && 338ac04195bSKonstantin Belousov !TD_IS_SUSPENDED(td)) { 339ac04195bSKonstantin Belousov thread_unlock(td); 340ac04195bSKonstantin Belousov breakout = 1; 341ac04195bSKonstantin Belousov break; 342ac04195bSKonstantin Belousov } 343ac04195bSKonstantin Belousov thread_unlock(td); 344ac04195bSKonstantin Belousov } 345ac04195bSKonstantin Belousov if (breakout) { 346ac04195bSKonstantin Belousov PROC_UNLOCK(p); 347ac04195bSKonstantin Belousov continue; 348ac04195bSKonstantin Belousov } 349ac04195bSKonstantin Belousov /* 350ac04195bSKonstantin Belousov * get a limit 351ac04195bSKonstantin Belousov */ 352ac04195bSKonstantin Belousov lim_rlimit_proc(p, RLIMIT_RSS, &rsslim); 353ac04195bSKonstantin Belousov limit = OFF_TO_IDX( 354ac04195bSKonstantin Belousov qmin(rsslim.rlim_cur, rsslim.rlim_max)); 355ac04195bSKonstantin Belousov 356ac04195bSKonstantin Belousov vm = vmspace_acquire_ref(p); 357*8370e9dfSMark Johnston _PHOLD(p); 358ac04195bSKonstantin Belousov PROC_UNLOCK(p); 359ac04195bSKonstantin Belousov if (vm == NULL) { 360ac04195bSKonstantin Belousov PRELE(p); 361ac04195bSKonstantin Belousov continue; 362ac04195bSKonstantin Belousov } 363ac04195bSKonstantin Belousov sx_sunlock(&allproc_lock); 364ac04195bSKonstantin Belousov 365ac04195bSKonstantin Belousov size = vmspace_resident_count(vm); 366ac04195bSKonstantin Belousov if (size >= limit) { 367ac04195bSKonstantin Belousov vm_swapout_map_deactivate_pages( 368ac04195bSKonstantin Belousov &vm->vm_map, limit); 369ac04195bSKonstantin Belousov size = vmspace_resident_count(vm); 370ac04195bSKonstantin Belousov } 371ac04195bSKonstantin Belousov if (racct_enable) { 372ac04195bSKonstantin Belousov rsize = IDX_TO_OFF(size); 373ac04195bSKonstantin Belousov PROC_LOCK(p); 374ac04195bSKonstantin Belousov if (p->p_state == PRS_NORMAL) 375ac04195bSKonstantin Belousov racct_set(p, RACCT_RSS, rsize); 376ac04195bSKonstantin Belousov ravailable = racct_get_available(p, RACCT_RSS); 377ac04195bSKonstantin Belousov PROC_UNLOCK(p); 378ac04195bSKonstantin Belousov if (rsize > ravailable) { 379ac04195bSKonstantin Belousov /* 380ac04195bSKonstantin Belousov * Don't be overly aggressive; this 381ac04195bSKonstantin Belousov * might be an innocent process, 382ac04195bSKonstantin Belousov * and the limit could've been exceeded 383ac04195bSKonstantin Belousov * by some memory hog. Don't try 384ac04195bSKonstantin Belousov * to deactivate more than 1/4th 385ac04195bSKonstantin Belousov * of process' resident set size. 386ac04195bSKonstantin Belousov */ 387ac04195bSKonstantin Belousov if (attempts <= 8) { 388ac04195bSKonstantin Belousov if (ravailable < rsize - 389ac04195bSKonstantin Belousov (rsize / 4)) { 390ac04195bSKonstantin Belousov ravailable = rsize - 391ac04195bSKonstantin Belousov (rsize / 4); 392ac04195bSKonstantin Belousov } 393ac04195bSKonstantin Belousov } 394ac04195bSKonstantin Belousov vm_swapout_map_deactivate_pages( 395ac04195bSKonstantin Belousov &vm->vm_map, 396ac04195bSKonstantin Belousov OFF_TO_IDX(ravailable)); 397ac04195bSKonstantin Belousov /* Update RSS usage after paging out. */ 398ac04195bSKonstantin Belousov size = vmspace_resident_count(vm); 399ac04195bSKonstantin Belousov rsize = IDX_TO_OFF(size); 400ac04195bSKonstantin Belousov PROC_LOCK(p); 401ac04195bSKonstantin Belousov if (p->p_state == PRS_NORMAL) 402ac04195bSKonstantin Belousov racct_set(p, RACCT_RSS, rsize); 403ac04195bSKonstantin Belousov PROC_UNLOCK(p); 404ac04195bSKonstantin Belousov if (rsize > ravailable) 405ac04195bSKonstantin Belousov tryagain = 1; 406ac04195bSKonstantin Belousov } 407ac04195bSKonstantin Belousov } 408ac04195bSKonstantin Belousov vmspace_free(vm); 409ac04195bSKonstantin Belousov sx_slock(&allproc_lock); 410ac04195bSKonstantin Belousov PRELE(p); 411ac04195bSKonstantin Belousov } 412ac04195bSKonstantin Belousov sx_sunlock(&allproc_lock); 4139997c048SKonstantin Belousov if (tryagain != 0 && attempts <= 10) { 4149997c048SKonstantin Belousov maybe_yield(); 415ac04195bSKonstantin Belousov goto again; 416ac04195bSKonstantin Belousov } 417ac04195bSKonstantin Belousov } 4189997c048SKonstantin Belousov } 419