vm_pageout.c revision 34321
118334Speter/* 290075Sobrien * Copyright (c) 1991 Regents of the University of California. 390075Sobrien * All rights reserved. 418334Speter * Copyright (c) 1994 John S. Dyson 590075Sobrien * All rights reserved. 618334Speter * Copyright (c) 1994 David Greenman 790075Sobrien * All rights reserved. 890075Sobrien * 990075Sobrien * This code is derived from software contributed to Berkeley by 1090075Sobrien * The Mach Operating System project at Carnegie-Mellon University. 1118334Speter * 1290075Sobrien * Redistribution and use in source and binary forms, with or without 1390075Sobrien * modification, are permitted provided that the following conditions 1490075Sobrien * are met: 1590075Sobrien * 1. Redistributions of source code must retain the above copyright 1618334Speter * notice, this list of conditions and the following disclaimer. 1718334Speter * 2. Redistributions in binary form must reproduce the above copyright 1890075Sobrien * notice, this list of conditions and the following disclaimer in the 1990075Sobrien * documentation and/or other materials provided with the distribution. 2090075Sobrien * 3. All advertising materials mentioning features or use of this software 2118334Speter * must display the following acknowledgement: 2218334Speter * This product includes software developed by the University of 2350397Sobrien * California, Berkeley and its contributors. 2450397Sobrien * 4. Neither the name of the University nor the names of its contributors 2550397Sobrien * may be used to endorse or promote products derived from this software 2650397Sobrien * without specific prior written permission. 2718334Speter * 2890075Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2918334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3018334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3118334Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3290075Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3318334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3490075Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3518334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3652284Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3718334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3818334Speter * SUCH DAMAGE. 3918334Speter * 4090075Sobrien * from: @(#)vm_pageout.c 7.4 (Berkeley) 5/7/91 4118334Speter * 4250397Sobrien * 4390075Sobrien * Copyright (c) 1987, 1990 Carnegie-Mellon University. 4496263Sobrien * All rights reserved. 4518334Speter * 4618334Speter * Authors: Avadis Tevanian, Jr., Michael Wayne Young 4718334Speter * 4818334Speter * Permission to use, copy, modify and distribute this software and 4918334Speter * its documentation is hereby granted, provided that both the copyright 5018334Speter * notice and this permission notice appear in all copies of the 5118334Speter * software, derivative works or modified versions, and any portions 5218334Speter * thereof, and that both notices appear in supporting documentation. 5318334Speter * 5418334Speter * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 5518334Speter * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 5618334Speter * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 5718334Speter * 5818334Speter * Carnegie Mellon requests users of this software to return to 5918334Speter * 6018334Speter * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 6152284Sobrien * School of Computer Science 6252284Sobrien * Carnegie Mellon University 6352284Sobrien * Pittsburgh PA 15213-3890 6452284Sobrien * 6518334Speter * any improvements or extensions that they make and grant Carnegie the 6618334Speter * rights to redistribute these changes. 6718334Speter * 6818334Speter * $Id: vm_pageout.c,v 1.118 1998/03/07 21:37:19 dyson Exp $ 6918334Speter */ 7018334Speter 7118334Speter/* 7218334Speter * The proverbial page-out daemon. 7318334Speter */ 7418334Speter 7518334Speter#include <sys/param.h> 7618334Speter#include <sys/systm.h> 7718334Speter#include <sys/kernel.h> 7818334Speter#include <sys/proc.h> 7918334Speter#include <sys/resourcevar.h> 8018334Speter#include <sys/signalvar.h> 8190075Sobrien#include <sys/vnode.h> 8218334Speter#include <sys/vmmeter.h> 8390075Sobrien#include <sys/sysctl.h> 8490075Sobrien 8590075Sobrien#include <vm/vm.h> 8690075Sobrien#include <vm/vm_param.h> 8718334Speter#include <vm/vm_prot.h> 8818334Speter#include <sys/lock.h> 8950397Sobrien#include <vm/vm_object.h> 9018334Speter#include <vm/vm_page.h> 9118334Speter#include <vm/vm_map.h> 9218334Speter#include <vm/vm_pageout.h> 9318334Speter#include <vm/vm_pager.h> 9418334Speter#include <vm/swap_pager.h> 9518334Speter#include <vm/vm_extern.h> 9618334Speter 9718334Speter/* 9818334Speter * System initialization 9918334Speter */ 10018334Speter 10118334Speter/* the kernel process "vm_pageout"*/ 10218334Speterstatic void vm_pageout __P((void)); 10318334Speterstatic int vm_pageout_clean __P((vm_page_t)); 10418334Speterstatic int vm_pageout_scan __P((void)); 10518334Speterstatic int vm_pageout_free_page_calc __P((vm_size_t count)); 10618334Speterstruct proc *pageproc; 10718334Speter 10818334Speterstatic struct kproc_desc page_kp = { 10918334Speter "pagedaemon", 11018334Speter vm_pageout, 11118334Speter &pageproc 11218334Speter}; 11318334SpeterSYSINIT_KT(pagedaemon, SI_SUB_KTHREAD_PAGE, SI_ORDER_FIRST, kproc_start, &page_kp) 11418334Speter 11518334Speter#if !defined(NO_SWAPPING) 11618334Speter/* the kernel process "vm_daemon"*/ 11718334Speterstatic void vm_daemon __P((void)); 11818334Speterstatic struct proc *vmproc; 11918334Speter 12018334Speterstatic struct kproc_desc vm_kp = { 12118334Speter "vmdaemon", 12290075Sobrien vm_daemon, 12318334Speter &vmproc 12452284Sobrien}; 12518334SpeterSYSINIT_KT(vmdaemon, SI_SUB_KTHREAD_VM, SI_ORDER_FIRST, kproc_start, &vm_kp) 12618334Speter#endif 12718334Speter 12852284Sobrien 12952284Sobrienint vm_pages_needed=0; /* Event on which pageout daemon sleeps */ 13052284Sobrienint vm_pageout_deficit=0; /* Estimated number of pages deficit */ 13150397Sobrienint vm_pageout_pages_needed=0; /* flag saying that the pageout daemon needs pages */ 13252284Sobrien 13318334Speterextern int npendingio; 13418334Speter#if !defined(NO_SWAPPING) 13518334Speterstatic int vm_pageout_req_swapout; /* XXX */ 13618334Speterstatic int vm_daemon_needed; 13718334Speter#endif 13850397Sobrienextern int nswiodone; 13950397Sobrienextern int vm_swap_size; 14018334Speterextern int vfs_update_wakeup; 14118334Speterstatic int vm_pageout_stats_max=0, vm_pageout_stats_interval = 0; 14250397Sobrienstatic int vm_pageout_full_stats_interval = 0; 14350397Sobrienstatic int vm_pageout_stats_free_max=0, vm_pageout_algorithm_lru=0; 14450397Sobrienstatic int defer_swap_pageouts=0; 14550397Sobrienstatic int disable_swap_pageouts=0; 14650397Sobrien 14750397Sobrienstatic int max_page_launder=100; 14818334Speter#if defined(NO_SWAPPING) 14918334Speterstatic int vm_swap_enabled=0; 15018334Speterstatic int vm_swap_idle_enabled=0; 15118334Speter#else 15218334Speterstatic int vm_swap_enabled=1; 15318334Speterstatic int vm_swap_idle_enabled=0; 15418334Speter#endif 15518334Speter 15618334SpeterSYSCTL_INT(_vm, VM_PAGEOUT_ALGORITHM, pageout_algorithm, 15718334Speter CTLFLAG_RW, &vm_pageout_algorithm_lru, 0, ""); 15818334Speter 15918334SpeterSYSCTL_INT(_vm, OID_AUTO, pageout_stats_max, 16018334Speter CTLFLAG_RW, &vm_pageout_stats_max, 0, ""); 16118334Speter 16252284SobrienSYSCTL_INT(_vm, OID_AUTO, pageout_full_stats_interval, 16352284Sobrien CTLFLAG_RW, &vm_pageout_full_stats_interval, 0, ""); 16452284Sobrien 16552284SobrienSYSCTL_INT(_vm, OID_AUTO, pageout_stats_interval, 16652284Sobrien CTLFLAG_RW, &vm_pageout_stats_interval, 0, ""); 16718334Speter 16818334SpeterSYSCTL_INT(_vm, OID_AUTO, pageout_stats_free_max, 16918334Speter CTLFLAG_RW, &vm_pageout_stats_free_max, 0, ""); 17090075Sobrien 17152284Sobrien#if defined(NO_SWAPPING) 17252284SobrienSYSCTL_INT(_vm, VM_SWAPPING_ENABLED, swap_enabled, 17318334Speter CTLFLAG_RD, &vm_swap_enabled, 0, ""); 17418334SpeterSYSCTL_INT(_vm, OID_AUTO, swap_idle_enabled, 17552284Sobrien CTLFLAG_RD, &vm_swap_idle_enabled, 0, ""); 17652284Sobrien#else 17752284SobrienSYSCTL_INT(_vm, VM_SWAPPING_ENABLED, swap_enabled, 17852284Sobrien CTLFLAG_RW, &vm_swap_enabled, 0, ""); 17952284SobrienSYSCTL_INT(_vm, OID_AUTO, swap_idle_enabled, 18018334Speter CTLFLAG_RW, &vm_swap_idle_enabled, 0, ""); 18152284Sobrien#endif 18252284Sobrien 18352284SobrienSYSCTL_INT(_vm, OID_AUTO, defer_swapspace_pageouts, 18452284Sobrien CTLFLAG_RW, &defer_swap_pageouts, 0, ""); 18552284Sobrien 18618334SpeterSYSCTL_INT(_vm, OID_AUTO, disable_swapspace_pageouts, 18752284Sobrien CTLFLAG_RW, &disable_swap_pageouts, 0, ""); 18852284Sobrien 18952284SobrienSYSCTL_INT(_vm, OID_AUTO, max_page_launder, 19018334Speter CTLFLAG_RW, &max_page_launder, 0, ""); 19152284Sobrien 19252284Sobrien 19352284Sobrien#define VM_PAGEOUT_PAGE_COUNT 16 19452284Sobrienint vm_pageout_page_count = VM_PAGEOUT_PAGE_COUNT; 19552284Sobrien 19618334Speterint vm_page_max_wired; /* XXX max # of wired pages system-wide */ 19718334Speter 19852284Sobrien#if !defined(NO_SWAPPING) 19952284Sobrientypedef void freeer_fcn_t __P((vm_map_t, vm_object_t, vm_pindex_t, int)); 20052284Sobrienstatic void vm_pageout_map_deactivate_pages __P((vm_map_t, vm_pindex_t)); 20152284Sobrienstatic freeer_fcn_t vm_pageout_object_deactivate_pages; 20252284Sobrienstatic void vm_req_vmdaemon __P((void)); 20352284Sobrien#endif 20450397Sobrienstatic void vm_pageout_page_stats(void); 20552284Sobrienvoid pmap_collect(void); 20652284Sobrien 20752284Sobrien/* 20852284Sobrien * vm_pageout_clean: 20952284Sobrien * 21050397Sobrien * Clean the page and remove it from the laundry. 21152284Sobrien * 21252284Sobrien * We set the busy bit to cause potential page faults on this page to 21352284Sobrien * block. 21452284Sobrien * 21518334Speter * And we set pageout-in-progress to keep the object from disappearing 21618334Speter * during pageout. This guarantees that the page won't move from the 21718334Speter * inactive queue. (However, any other page on the inactive queue may 21818334Speter * move!) 21918334Speter */ 22018334Speterstatic int 22118334Spetervm_pageout_clean(m) 22218334Speter vm_page_t m; 22318334Speter{ 22418334Speter register vm_object_t object; 22518334Speter vm_page_t mc[2*vm_pageout_page_count]; 22618334Speter int pageout_count; 22718334Speter int i, forward_okay, backward_okay, page_base; 22818334Speter vm_pindex_t pindex = m->pindex; 22990075Sobrien 23018334Speter object = m->object; 23118334Speter 23218334Speter /* 23318334Speter * If not OBJT_SWAP, additional memory may be needed to do the pageout. 23418334Speter * Try to avoid the deadlock. 23518334Speter */ 23618334Speter if ((object->type == OBJT_DEFAULT) && 23718334Speter ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_pageout_free_min)) 23818334Speter return 0; 23990075Sobrien 24018334Speter /* 24152284Sobrien * Don't mess with the page if it's busy. 24290075Sobrien */ 24318334Speter if ((m->hold_count != 0) || 24490075Sobrien ((m->busy != 0) || (m->flags & PG_BUSY))) 24590075Sobrien return 0; 24690075Sobrien 24790075Sobrien /* 24818334Speter * Try collapsing before it's too late. 24918334Speter */ 25018334Speter if (object->backing_object) { 25118334Speter vm_object_collapse(object); 25218334Speter } 25318334Speter 25418334Speter mc[vm_pageout_page_count] = m; 25518334Speter pageout_count = 1; 25618334Speter page_base = vm_pageout_page_count; 25718334Speter forward_okay = TRUE; 25818334Speter if (pindex != 0) 25918334Speter backward_okay = TRUE; 26018334Speter else 26118334Speter backward_okay = FALSE; 26218334Speter /* 26318334Speter * Scan object for clusterable pages. 26418334Speter * 26518334Speter * We can cluster ONLY if: ->> the page is NOT 26618334Speter * clean, wired, busy, held, or mapped into a 26718334Speter * buffer, and one of the following: 26818334Speter * 1) The page is inactive, or a seldom used 26952284Sobrien * active page. 27018334Speter * -or- 27152284Sobrien * 2) we force the issue. 27252284Sobrien */ 27352284Sobrien for (i = 1; (i < vm_pageout_page_count) && (forward_okay || backward_okay); i++) { 27452284Sobrien vm_page_t p; 27552284Sobrien 27690075Sobrien /* 27718334Speter * See if forward page is clusterable. 27818334Speter */ 27990075Sobrien if (forward_okay) { 28090075Sobrien /* 28190075Sobrien * Stop forward scan at end of object. 28290075Sobrien */ 28318334Speter if ((pindex + i) > object->size) { 28418334Speter forward_okay = FALSE; 28518334Speter goto do_backward; 28652284Sobrien } 28752284Sobrien p = vm_page_lookup(object, pindex + i); 28852284Sobrien if (p) { 28952284Sobrien if (((p->queue - p->pc) == PQ_CACHE) || 29052284Sobrien (p->flags & PG_BUSY) || p->busy) { 29152284Sobrien forward_okay = FALSE; 29252284Sobrien goto do_backward; 29352284Sobrien } 29452284Sobrien vm_page_test_dirty(p); 29552284Sobrien if ((p->dirty & p->valid) != 0 && 29652284Sobrien (p->queue == PQ_INACTIVE) && 29752284Sobrien (p->wire_count == 0) && 29818334Speter (p->hold_count == 0)) { 29918334Speter mc[vm_pageout_page_count + i] = p; 30018334Speter pageout_count++; 30118334Speter if (pageout_count == vm_pageout_page_count) 30218334Speter break; 30318334Speter } else { 30452284Sobrien forward_okay = FALSE; 30518334Speter } 30650397Sobrien } else { 30750397Sobrien forward_okay = FALSE; 30850397Sobrien } 30950397Sobrien } 31018334Speterdo_backward: 31150397Sobrien /* 31250397Sobrien * See if backward page is clusterable. 31350397Sobrien */ 31450397Sobrien if (backward_okay) { 31518334Speter /* 31618334Speter * Stop backward scan at beginning of object. 31718334Speter */ 31818334Speter if ((pindex - i) == 0) { 31950397Sobrien backward_okay = FALSE; 32050397Sobrien } 32152284Sobrien p = vm_page_lookup(object, pindex - i); 32218334Speter if (p) { 32390075Sobrien if (((p->queue - p->pc) == PQ_CACHE) || 32452284Sobrien (p->flags & PG_BUSY) || p->busy) { 32552284Sobrien backward_okay = FALSE; 32690075Sobrien continue; 32790075Sobrien } 32852284Sobrien vm_page_test_dirty(p); 32990075Sobrien if ((p->dirty & p->valid) != 0 && 33090075Sobrien (p->queue == PQ_INACTIVE) && 33152284Sobrien (p->wire_count == 0) && 33252284Sobrien (p->hold_count == 0)) { 33318334Speter mc[vm_pageout_page_count - i] = p; 33418334Speter pageout_count++; 33518334Speter page_base--; 33618334Speter if (pageout_count == vm_pageout_page_count) 33718334Speter break; 33818334Speter } else { 33918334Speter backward_okay = FALSE; 34018334Speter } 34118334Speter } else { 34218334Speter backward_okay = FALSE; 34390075Sobrien } 34418334Speter } 34518334Speter } 34618334Speter 34718334Speter /* 34852284Sobrien * we allow reads during pageouts... 34918334Speter */ 35018334Speter return vm_pageout_flush(&mc[page_base], pageout_count, 0); 35118334Speter} 35252284Sobrien 35352284Sobrienint 35452284Sobrienvm_pageout_flush(mc, count, flags) 35518334Speter vm_page_t *mc; 35618334Speter int count; 35718334Speter int flags; 35818334Speter{ 35918334Speter register vm_object_t object; 36018334Speter int pageout_status[count]; 36118334Speter int numpagedout = 0; 36218334Speter int i; 36318334Speter 36418334Speter for (i = 0; i < count; i++) { 36518334Speter mc[i]->busy++; 36618334Speter vm_page_protect(mc[i], VM_PROT_READ); 36718334Speter } 36818334Speter 36918334Speter object = mc[0]->object; 37090075Sobrien object->paging_in_progress += count; 37190075Sobrien 37290075Sobrien vm_pager_put_pages(object, mc, count, 37390075Sobrien (flags | ((object == kernel_object) ? OBJPC_SYNC : 0)), 37490075Sobrien pageout_status); 37590075Sobrien 37690075Sobrien for (i = 0; i < count; i++) { 37790075Sobrien vm_page_t mt = mc[i]; 37890075Sobrien 37990075Sobrien switch (pageout_status[i]) { 38052284Sobrien case VM_PAGER_OK: 38190075Sobrien numpagedout++; 38290075Sobrien break; 38390075Sobrien case VM_PAGER_PEND: 38490075Sobrien numpagedout++; 38590075Sobrien break; 38690075Sobrien case VM_PAGER_BAD: 38790075Sobrien /* 38890075Sobrien * Page outside of range of object. Right now we 38990075Sobrien * essentially lose the changes by pretending it 39090075Sobrien * worked. 39190075Sobrien */ 39290075Sobrien pmap_clear_modify(VM_PAGE_TO_PHYS(mt)); 39390075Sobrien mt->dirty = 0; 39490075Sobrien break; 39590075Sobrien case VM_PAGER_ERROR: 39690075Sobrien case VM_PAGER_FAIL: 39790075Sobrien /* 39890075Sobrien * If page couldn't be paged out, then reactivate the 39990075Sobrien * page so it doesn't clog the inactive list. (We 40090075Sobrien * will try paging out it again later). 40190075Sobrien */ 40290075Sobrien vm_page_activate(mt); 40390075Sobrien break; 40490075Sobrien case VM_PAGER_AGAIN: 40590075Sobrien break; 40690075Sobrien } 40790075Sobrien 40890075Sobrien /* 40990075Sobrien * If the operation is still going, leave the page busy to 41090075Sobrien * block all other accesses. Also, leave the paging in 41190075Sobrien * progress indicator set so that we don't attempt an object 41290075Sobrien * collapse. 41390075Sobrien */ 41490075Sobrien if (pageout_status[i] != VM_PAGER_PEND) { 41590075Sobrien vm_object_pip_wakeup(object); 41690075Sobrien PAGE_BWAKEUP(mt); 41790075Sobrien } 41890075Sobrien } 41990075Sobrien return numpagedout; 42090075Sobrien} 42190075Sobrien 42290075Sobrien#if !defined(NO_SWAPPING) 42390075Sobrien/* 42490075Sobrien * vm_pageout_object_deactivate_pages 42590075Sobrien * 42690075Sobrien * deactivate enough pages to satisfy the inactive target 42790075Sobrien * requirements or if vm_page_proc_limit is set, then 42890075Sobrien * deactivate all of the pages in the object and its 42990075Sobrien * backing_objects. 43090075Sobrien * 43190075Sobrien * The object and map must be locked. 43290075Sobrien */ 43390075Sobrienstatic void 43490075Sobrienvm_pageout_object_deactivate_pages(map, object, desired, map_remove_only) 43590075Sobrien vm_map_t map; 43690075Sobrien vm_object_t object; 43790075Sobrien vm_pindex_t desired; 43890075Sobrien int map_remove_only; 43990075Sobrien{ 44090075Sobrien register vm_page_t p, next; 44190075Sobrien int rcount; 44290075Sobrien int remove_mode; 44390075Sobrien int s; 44490075Sobrien 44590075Sobrien if (object->type == OBJT_DEVICE) 44690075Sobrien return; 44790075Sobrien 44890075Sobrien while (object) { 44990075Sobrien if (vm_map_pmap(map)->pm_stats.resident_count <= desired) 45090075Sobrien return; 45190075Sobrien if (object->paging_in_progress) 45290075Sobrien return; 45352284Sobrien 45490075Sobrien remove_mode = map_remove_only; 45552284Sobrien if (object->shadow_count > 1) 45690075Sobrien remove_mode = 1; 45790075Sobrien /* 45890075Sobrien * scan the objects entire memory queue 45990075Sobrien */ 46090075Sobrien rcount = object->resident_page_count; 46190075Sobrien p = TAILQ_FIRST(&object->memq); 46290075Sobrien while (p && (rcount-- > 0)) { 46396263Sobrien int actcount; 46490075Sobrien if (vm_map_pmap(map)->pm_stats.resident_count <= desired) 46518334Speter return; 46618334Speter next = TAILQ_NEXT(p, listq); 46718334Speter cnt.v_pdpages++; 46818334Speter if (p->wire_count != 0 || 46918334Speter p->hold_count != 0 || 47018334Speter p->busy != 0 || 47190075Sobrien (p->flags & PG_BUSY) || 47218334Speter !pmap_page_exists(vm_map_pmap(map), VM_PAGE_TO_PHYS(p))) { 47318334Speter p = next; 47418334Speter continue; 47518334Speter } 47618334Speter 47790075Sobrien actcount = pmap_ts_referenced(VM_PAGE_TO_PHYS(p)); 47850397Sobrien if (actcount) { 47950397Sobrien p->flags |= PG_REFERENCED; 48090075Sobrien } else if (p->flags & PG_REFERENCED) { 48190075Sobrien actcount = 1; 48250397Sobrien } 48318334Speter 48418334Speter if ((p->queue != PQ_ACTIVE) && 48518334Speter (p->flags & PG_REFERENCED)) { 48618334Speter vm_page_activate(p); 48718334Speter p->act_count += actcount; 48850397Sobrien p->flags &= ~PG_REFERENCED; 48918334Speter } else if (p->queue == PQ_ACTIVE) { 49018334Speter if ((p->flags & PG_REFERENCED) == 0) { 49118334Speter p->act_count -= min(p->act_count, ACT_DECLINE); 49218334Speter if (!remove_mode && (vm_pageout_algorithm_lru || (p->act_count == 0))) { 49350397Sobrien vm_page_protect(p, VM_PROT_NONE); 49418334Speter vm_page_deactivate(p); 49518334Speter } else { 49618334Speter s = splvm(); 49718334Speter TAILQ_REMOVE(&vm_page_queue_active, p, pageq); 49818334Speter TAILQ_INSERT_TAIL(&vm_page_queue_active, p, pageq); 49918334Speter splx(s); 50050397Sobrien } 50150397Sobrien } else { 50250397Sobrien vm_page_activate(p); 50390075Sobrien p->flags &= ~PG_REFERENCED; 50418334Speter if (p->act_count < (ACT_MAX - ACT_ADVANCE)) 50518334Speter p->act_count += ACT_ADVANCE; 50618334Speter s = splvm(); 50718334Speter TAILQ_REMOVE(&vm_page_queue_active, p, pageq); 50818334Speter TAILQ_INSERT_TAIL(&vm_page_queue_active, p, pageq); 50918334Speter splx(s); 51018334Speter } 51118334Speter } else if (p->queue == PQ_INACTIVE) { 51218334Speter vm_page_protect(p, VM_PROT_NONE); 51318334Speter } 51450397Sobrien p = next; 51518334Speter } 51652284Sobrien object = object->backing_object; 51790075Sobrien } 51890075Sobrien return; 51990075Sobrien} 52052284Sobrien 52150397Sobrien/* 52252284Sobrien * deactivate some number of pages in a map, try to do it fairly, but 52352284Sobrien * that is really hard to do. 52450397Sobrien */ 52552284Sobrienstatic void 52652284Sobrienvm_pageout_map_deactivate_pages(map, desired) 52752284Sobrien vm_map_t map; 52852284Sobrien vm_pindex_t desired; 52952284Sobrien{ 53050397Sobrien vm_map_entry_t tmpe; 53152284Sobrien vm_object_t obj, bigobj; 53252284Sobrien 53352284Sobrien if (lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, (void *)0, curproc)) { 53452284Sobrien return; 53590075Sobrien } 53690075Sobrien 53750397Sobrien bigobj = NULL; 53852284Sobrien 53952284Sobrien /* 54052284Sobrien * first, search out the biggest object, and try to free pages from 54152284Sobrien * that. 54252284Sobrien */ 54352284Sobrien tmpe = map->header.next; 54452284Sobrien while (tmpe != &map->header) { 54552284Sobrien if ((tmpe->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { 54652284Sobrien obj = tmpe->object.vm_object; 54752284Sobrien if ((obj != NULL) && (obj->shadow_count <= 1) && 54818334Speter ((bigobj == NULL) || 54918334Speter (bigobj->resident_page_count < obj->resident_page_count))) { 55052284Sobrien bigobj = obj; 55152284Sobrien } 55290075Sobrien } 55352284Sobrien tmpe = tmpe->next; 55452284Sobrien } 55552284Sobrien 55652284Sobrien if (bigobj) 55752284Sobrien vm_pageout_object_deactivate_pages(map, bigobj, desired, 0); 55890075Sobrien 55990075Sobrien /* 56052284Sobrien * Next, hunt around for other pages to deactivate. We actually 56152284Sobrien * do this search sort of wrong -- .text first is not the best idea. 56252284Sobrien */ 56352284Sobrien tmpe = map->header.next; 56452284Sobrien while (tmpe != &map->header) { 56590075Sobrien if (vm_map_pmap(map)->pm_stats.resident_count <= desired) 56652284Sobrien break; 56752284Sobrien if ((tmpe->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) == 0) { 56852284Sobrien obj = tmpe->object.vm_object; 56952284Sobrien if (obj) 57052284Sobrien vm_pageout_object_deactivate_pages(map, obj, desired, 0); 57152284Sobrien } 57252284Sobrien tmpe = tmpe->next; 57352284Sobrien }; 57452284Sobrien 57552284Sobrien /* 57652284Sobrien * Remove all mappings if a process is swapped out, this will free page 57752284Sobrien * table pages. 57852284Sobrien */ 57952284Sobrien if (desired == 0) 58052284Sobrien pmap_remove(vm_map_pmap(map), 58152284Sobrien VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); 58252284Sobrien vm_map_unlock(map); 58390075Sobrien return; 58490075Sobrien} 58590075Sobrien#endif 58690075Sobrien 58790075Sobrienvoid 58890075Sobrienvm_pageout_page_free(vm_page_t m) { 58990075Sobrien struct vnode *vp; 59090075Sobrien vm_object_t object; 59190075Sobrien 59290075Sobrien object = m->object; 59390075Sobrien object->ref_count++; 59490075Sobrien 59590075Sobrien if (object->type == OBJT_VNODE) { 59690075Sobrien vp = object->handle; 59790075Sobrien vp->v_usecount++; 59890075Sobrien if (VSHOULDBUSY(vp)) 59990075Sobrien vbusy(vp); 60090075Sobrien } 60190075Sobrien 60290075Sobrien m->flags |= PG_BUSY; 60390075Sobrien vm_page_protect(m, VM_PROT_NONE); 60490075Sobrien vm_page_free(m); 60590075Sobrien vm_object_deallocate(object); 60690075Sobrien} 60790075Sobrien 60890075Sobrien/* 60990075Sobrien * vm_pageout_scan does the dirty work for the pageout daemon. 61090075Sobrien */ 61190075Sobrienstatic int 61290075Sobrienvm_pageout_scan() 61390075Sobrien{ 61490075Sobrien vm_page_t m, next; 61590075Sobrien int page_shortage, addl_page_shortage, maxscan, pcount; 61690075Sobrien int maxlaunder; 61790075Sobrien int pages_freed; 61890075Sobrien struct proc *p, *bigproc; 61990075Sobrien vm_offset_t size, bigsize; 62090075Sobrien vm_object_t object; 62190075Sobrien int force_wakeup = 0; 62290075Sobrien int actcount; 62390075Sobrien int vnodes_skipped = 0; 62490075Sobrien int s; 62590075Sobrien 62690075Sobrien /* 62790075Sobrien * Do whatever cleanup that the pmap code can. 62890075Sobrien */ 62990075Sobrien pmap_collect(); 63090075Sobrien 63190075Sobrien /* 63290075Sobrien * Start scanning the inactive queue for pages we can free. We keep 63390075Sobrien * scanning until we have enough free pages or we have scanned through 63490075Sobrien * the entire queue. If we encounter dirty pages, we start cleaning 63590075Sobrien * them. 63690075Sobrien */ 63790075Sobrien 63890075Sobrien pages_freed = 0; 63990075Sobrien addl_page_shortage = vm_pageout_deficit; 64090075Sobrien vm_pageout_deficit = 0; 64190075Sobrien 64290075Sobrien if (max_page_launder == 0) 64390075Sobrien max_page_launder = 1; 64490075Sobrien maxlaunder = (cnt.v_inactive_target > max_page_launder) ? 64590075Sobrien max_page_launder : cnt.v_inactive_target; 64690075Sobrien 64752284Sobrienrescan0: 64852284Sobrien maxscan = cnt.v_inactive_count; 64952284Sobrien for( m = TAILQ_FIRST(&vm_page_queue_inactive); 65052284Sobrien 65152284Sobrien (m != NULL) && (maxscan-- > 0) && 65252284Sobrien ((cnt.v_cache_count + cnt.v_free_count) < 65352284Sobrien (cnt.v_cache_min + cnt.v_free_target)); 65452284Sobrien 65552284Sobrien m = next) { 65652284Sobrien 65752284Sobrien cnt.v_pdpages++; 65818334Speter 65918334Speter if (m->queue != PQ_INACTIVE) { 66018334Speter goto rescan0; 66118334Speter } 66218334Speter 66318334Speter next = TAILQ_NEXT(m, pageq); 66418334Speter 66518334Speter if (m->hold_count) { 66618334Speter s = splvm(); 66718334Speter TAILQ_REMOVE(&vm_page_queue_inactive, m, pageq); 66818334Speter TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 66918334Speter splx(s); 67018334Speter addl_page_shortage++; 67118334Speter continue; 67290075Sobrien } 67318334Speter /* 67418334Speter * Dont mess with busy pages, keep in the front of the 67518334Speter * queue, most likely are being paged out. 67690075Sobrien */ 67790075Sobrien if (m->busy || (m->flags & PG_BUSY)) { 67890075Sobrien addl_page_shortage++; 67918334Speter continue; 68050397Sobrien } 68150397Sobrien 68290075Sobrien /* 68350397Sobrien * If the object is not being used, we ignore previous references. 68450397Sobrien */ 68552284Sobrien if (m->object->ref_count == 0) { 68652284Sobrien m->flags &= ~PG_REFERENCED; 68718334Speter pmap_clear_reference(VM_PAGE_TO_PHYS(m)); 68852284Sobrien 68918334Speter /* 69052284Sobrien * Otherwise, if the page has been referenced while in the inactive 69118334Speter * queue, we bump the "activation count" upwards, making it less 69252284Sobrien * likely that the page will be added back to the inactive queue 69352284Sobrien * prematurely again. Here we check the page tables (or emulated 69490075Sobrien * bits, if any), given the upper level VM system not knowing anything 69518334Speter * about existing references. 69618334Speter */ 69718334Speter } else if (((m->flags & PG_REFERENCED) == 0) && 69818334Speter (actcount = pmap_ts_referenced(VM_PAGE_TO_PHYS(m)))) { 69918334Speter vm_page_activate(m); 70018334Speter m->act_count += (actcount + ACT_ADVANCE); 70118334Speter continue; 70218334Speter } 70318334Speter 70418334Speter /* 70590075Sobrien * If the upper level VM system knows about any page references, 70690075Sobrien * we activate the page. We also set the "activation count" higher 70718334Speter * than normal so that we will less likely place pages back onto the 70818334Speter * inactive queue again. 70918334Speter */ 71018334Speter if ((m->flags & PG_REFERENCED) != 0) { 71118334Speter m->flags &= ~PG_REFERENCED; 71218334Speter actcount = pmap_ts_referenced(VM_PAGE_TO_PHYS(m)); 71318334Speter vm_page_activate(m); 71418334Speter m->act_count += (actcount + ACT_ADVANCE + 1); 71518334Speter continue; 71618334Speter } 71718334Speter 71818334Speter /* 71950397Sobrien * If the upper level VM system doesn't know anything about the 72050397Sobrien * page being dirty, we have to check for it again. As far as the 72150397Sobrien * VM code knows, any partially dirty pages are fully dirty. 72250397Sobrien */ 72390075Sobrien if (m->dirty == 0) { 72490075Sobrien vm_page_test_dirty(m); 72550397Sobrien } else if (m->dirty != 0) { 72618334Speter m->dirty = VM_PAGE_BITS_ALL; 72718334Speter } 72818334Speter 72918334Speter /* 73018334Speter * Invalid pages can be easily freed 73118334Speter */ 73218334Speter if (m->valid == 0) { 73318334Speter vm_pageout_page_free(m); 73418334Speter cnt.v_dfree++; 73518334Speter pages_freed++; 73690075Sobrien 73790075Sobrien /* 73890075Sobrien * Clean pages can be placed onto the cache queue. 73990075Sobrien */ 74090075Sobrien } else if (m->dirty == 0) { 74190075Sobrien vm_page_cache(m); 74290075Sobrien pages_freed++; 74352284Sobrien 74452284Sobrien /* 74552284Sobrien * Dirty pages need to be paged out. Note that we clean 74690075Sobrien * only a limited number of pages per pagedaemon pass. 74718334Speter */ 74852284Sobrien } else if (maxlaunder > 0) { 74918334Speter int written; 75018334Speter int swap_pageouts_ok; 75118334Speter struct vnode *vp = NULL; 75218334Speter 75390075Sobrien object = m->object; 75490075Sobrien 75550397Sobrien if ((object->type != OBJT_SWAP) && (object->type != OBJT_DEFAULT)) { 75618334Speter swap_pageouts_ok = 1; 75752284Sobrien } else { 75818334Speter swap_pageouts_ok = !(defer_swap_pageouts || disable_swap_pageouts); 75918334Speter swap_pageouts_ok |= (!disable_swap_pageouts && defer_swap_pageouts && 76018334Speter (cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min); 76118334Speter 76290075Sobrien } 76390075Sobrien 76490075Sobrien /* 76590075Sobrien * We don't bother paging objects that are "dead". Those 76690075Sobrien * objects are in a "rundown" state. 76790075Sobrien */ 76890075Sobrien if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) { 76990075Sobrien s = splvm(); 77090075Sobrien TAILQ_REMOVE(&vm_page_queue_inactive, m, pageq); 77150397Sobrien TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 77250397Sobrien splx(s); 77350397Sobrien continue; 77450397Sobrien } 77518334Speter 77618334Speter if ((object->type == OBJT_VNODE) && 77718334Speter (object->flags & OBJ_DEAD) == 0) { 77818334Speter vp = object->handle; 77918334Speter if (VOP_ISLOCKED(vp) || 78052284Sobrien vget(vp, LK_EXCLUSIVE|LK_NOOBJ, curproc)) { 78152284Sobrien if ((m->queue == PQ_INACTIVE) && 78290075Sobrien (m->hold_count == 0) && 78390075Sobrien (m->busy == 0) && 78490075Sobrien (m->flags & PG_BUSY) == 0) { 78590075Sobrien s = splvm(); 78690075Sobrien TAILQ_REMOVE(&vm_page_queue_inactive, m, pageq); 78718334Speter TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 78818334Speter splx(s); 78918334Speter } 79018334Speter if (object->flags & OBJ_MIGHTBEDIRTY) 79118334Speter vnodes_skipped++; 79218334Speter continue; 79318334Speter } 79496263Sobrien 79596263Sobrien /* 79696263Sobrien * The page might have been moved to another queue 79796263Sobrien * during potential blocking in vget() above. 79896263Sobrien */ 79996263Sobrien if (m->queue != PQ_INACTIVE) { 80050397Sobrien if (object->flags & OBJ_MIGHTBEDIRTY) 80190075Sobrien vnodes_skipped++; 80290075Sobrien vput(vp); 80390075Sobrien continue; 80490075Sobrien } 80550397Sobrien 80652284Sobrien /* 80718334Speter * The page may have been busied during the blocking in 80852284Sobrien * vput(); We don't move the page back onto the end of 80952284Sobrien * the queue so that statistics are more correct if we don't. 81052284Sobrien */ 81152284Sobrien if (m->busy || (m->flags & PG_BUSY)) { 81252284Sobrien vput(vp); 81352284Sobrien continue; 81452284Sobrien } 81552284Sobrien 81652284Sobrien /* 81752284Sobrien * If the page has become held, then skip it 81852284Sobrien */ 81952284Sobrien if (m->hold_count) { 82052284Sobrien s = splvm(); 82152284Sobrien TAILQ_REMOVE(&vm_page_queue_inactive, m, pageq); 82218334Speter TAILQ_INSERT_TAIL(&vm_page_queue_inactive, m, pageq); 82318334Speter splx(s); 82418334Speter if (object->flags & OBJ_MIGHTBEDIRTY) 82518334Speter vnodes_skipped++; 82618334Speter vput(vp); 82718334Speter continue; 82818334Speter } 82918334Speter } 83018334Speter 83118334Speter /* 83218334Speter * If a page is dirty, then it is either being washed 83318334Speter * (but not yet cleaned) or it is still in the 83418334Speter * laundry. If it is still in the laundry, then we 83518334Speter * start the cleaning operation. 83652284Sobrien */ 83752284Sobrien written = vm_pageout_clean(m); 83818334Speter if (vp) 83918334Speter vput(vp); 84018334Speter 84118334Speter maxlaunder -= written; 84218334Speter } 84318334Speter } 84418334Speter 84518334Speter /* 84618334Speter * Compute the page shortage. If we are still very low on memory be 84718334Speter * sure that we will move a minimal amount of pages from active to 84818334Speter * inactive. 84952284Sobrien */ 85052284Sobrien page_shortage = (cnt.v_inactive_target + cnt.v_cache_min) - 85152284Sobrien (cnt.v_free_count + cnt.v_inactive_count + cnt.v_cache_count); 85218334Speter if (page_shortage <= 0) { 85390075Sobrien if (pages_freed == 0) { 85418334Speter page_shortage = cnt.v_free_min - (cnt.v_free_count + cnt.v_cache_count); 85518334Speter } else { 85618334Speter page_shortage = 1; 85752284Sobrien } 85818334Speter } 85918334Speter 86018334Speter /* 86118334Speter * If the "inactive" loop finds that there is a shortage over and 86250397Sobrien * above the page statistics variables, then we need to accomodate 86350397Sobrien * that. This avoids potential deadlocks due to pages being temporarily 86450397Sobrien * busy for I/O or other types of temporary wiring. 86550397Sobrien */ 86650397Sobrien if (addl_page_shortage) { 86718334Speter if (page_shortage < 0) 86850397Sobrien page_shortage = 0; 86918334Speter page_shortage += addl_page_shortage; 87050397Sobrien } 87150397Sobrien 87250397Sobrien pcount = cnt.v_active_count; 87318334Speter m = TAILQ_FIRST(&vm_page_queue_active); 87418334Speter while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) { 87518334Speter 87618334Speter /* 87718334Speter * This is a consistancy check, and should likely be a panic 87818334Speter * or warning. 87918334Speter */ 88018334Speter if (m->queue != PQ_ACTIVE) { 88118334Speter break; 88218334Speter } 88318334Speter 88418334Speter next = TAILQ_NEXT(m, pageq); 88518334Speter /* 88618334Speter * Don't deactivate pages that are busy. 88718334Speter */ 88818334Speter if ((m->busy != 0) || 88918334Speter (m->flags & PG_BUSY) || 89090075Sobrien (m->hold_count != 0)) { 89118334Speter s = splvm(); 89252284Sobrien TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 89318334Speter TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 89452284Sobrien splx(s); 89552284Sobrien m = next; 89690075Sobrien continue; 89718334Speter } 89818334Speter 89918334Speter /* 90018334Speter * The count for pagedaemon pages is done after checking the 90152284Sobrien * page for eligbility... 90218334Speter */ 90318334Speter cnt.v_pdpages++; 90490075Sobrien 90518334Speter /* 90618334Speter * Check to see "how much" the page has been used. 90718334Speter */ 90890075Sobrien actcount = 0; 90918334Speter if (m->object->ref_count != 0) { 91090075Sobrien if (m->flags & PG_REFERENCED) { 91118334Speter actcount += 1; 91252284Sobrien } 91352284Sobrien actcount += pmap_ts_referenced(VM_PAGE_TO_PHYS(m)); 91452284Sobrien if (actcount) { 91518334Speter m->act_count += ACT_ADVANCE + actcount; 91618334Speter if (m->act_count > ACT_MAX) 91718334Speter m->act_count = ACT_MAX; 91818334Speter } 91952284Sobrien } 92018334Speter 92152284Sobrien /* 92252284Sobrien * Since we have "tested" this bit, we need to clear it now. 92318334Speter */ 92450397Sobrien m->flags &= ~PG_REFERENCED; 92518334Speter 92690075Sobrien /* 92750397Sobrien * Only if an object is currently being used, do we use the 92850397Sobrien * page activation count stats. 92990075Sobrien */ 93090075Sobrien if (actcount && (m->object->ref_count != 0)) { 93190075Sobrien s = splvm(); 93250397Sobrien TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 93350397Sobrien TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 93450397Sobrien splx(s); 93552284Sobrien } else { 93652284Sobrien m->act_count -= min(m->act_count, ACT_DECLINE); 93718334Speter if (vm_pageout_algorithm_lru || 93818334Speter (m->object->ref_count == 0) || (m->act_count == 0)) { 93918334Speter page_shortage--; 94018334Speter if (m->object->ref_count == 0) { 94118334Speter vm_page_protect(m, VM_PROT_NONE); 94218334Speter if (m->dirty == 0) 94318334Speter vm_page_cache(m); 94418334Speter else 94518334Speter vm_page_deactivate(m); 94618334Speter } else { 94718334Speter vm_page_deactivate(m); 94818334Speter } 94918334Speter } else { 95018334Speter s = splvm(); 95118334Speter TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 95218334Speter TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 95318334Speter splx(s); 95418334Speter } 95518334Speter } 95618334Speter m = next; 95718334Speter } 95818334Speter 95918334Speter s = splvm(); 96018334Speter /* 96118334Speter * We try to maintain some *really* free pages, this allows interrupt 96218334Speter * code to be guaranteed space. 96318334Speter */ 96418334Speter while (cnt.v_free_count < cnt.v_free_reserved) { 96518334Speter static int cache_rover = 0; 96618334Speter m = vm_page_list_find(PQ_CACHE, cache_rover); 96718334Speter if (!m) 96818334Speter break; 96918334Speter cache_rover = (cache_rover + PQ_PRIME2) & PQ_L2_MASK; 97018334Speter vm_pageout_page_free(m); 97118334Speter cnt.v_dfree++; 97218334Speter } 97318334Speter splx(s); 97418334Speter 97518334Speter#if !defined(NO_SWAPPING) 97618334Speter /* 97718334Speter * Idle process swapout -- run once per second. 97818334Speter */ 97918334Speter if (vm_swap_idle_enabled) { 98018334Speter static long lsec; 98118334Speter if (time.tv_sec != lsec) { 98218334Speter vm_pageout_req_swapout |= VM_SWAP_IDLE; 98318334Speter vm_req_vmdaemon(); 98418334Speter lsec = time.tv_sec; 98518334Speter } 98618334Speter } 98718334Speter#endif 98818334Speter 98918334Speter /* 99018334Speter * If we didn't get enough free pages, and we have skipped a vnode 99118334Speter * in a writeable object, wakeup the sync daemon. And kick swapout 99218334Speter * if we did not get enough free pages. 99352284Sobrien */ 99452284Sobrien if ((cnt.v_cache_count + cnt.v_free_count) < 99552284Sobrien (cnt.v_free_target + cnt.v_cache_min) ) { 99652284Sobrien if (vnodes_skipped && 99752284Sobrien (cnt.v_cache_count + cnt.v_free_count) < cnt.v_free_min) { 99818334Speter if (!vfs_update_wakeup) { 99918334Speter vfs_update_wakeup = 1; 100052284Sobrien wakeup(&vfs_update_wakeup); 100118334Speter } 100252284Sobrien } 100352284Sobrien#if !defined(NO_SWAPPING) 100452284Sobrien if (vm_swap_enabled && 100518334Speter (cnt.v_free_count + cnt.v_cache_count < cnt.v_free_target)) { 100618334Speter vm_req_vmdaemon(); 100752284Sobrien vm_pageout_req_swapout |= VM_SWAP_NORMAL; 100818334Speter } 100990075Sobrien#endif 101052284Sobrien } 101118334Speter 101252284Sobrien 101318334Speter /* 101452284Sobrien * make sure that we have swap space -- if we are low on memory and 101552284Sobrien * swap -- then kill the biggest process. 101652284Sobrien */ 101752284Sobrien if ((vm_swap_size == 0 || swap_pager_full) && 101818334Speter ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min)) { 101952284Sobrien bigproc = NULL; 102052284Sobrien bigsize = 0; 102152284Sobrien for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 102252284Sobrien /* 102352284Sobrien * if this is a system process, skip it 102452284Sobrien */ 102518334Speter if ((p->p_flag & P_SYSTEM) || (p->p_pid == 1) || 102690075Sobrien ((p->p_pid < 48) && (vm_swap_size != 0))) { 102752284Sobrien continue; 102818334Speter } 102952284Sobrien /* 103052284Sobrien * if the process is in a non-running type state, 103152284Sobrien * don't touch it. 103218334Speter */ 103352284Sobrien if (p->p_stat != SRUN && p->p_stat != SSLEEP) { 103452284Sobrien continue; 103552284Sobrien } 103652284Sobrien /* 103752284Sobrien * get the process size 103852284Sobrien */ 103952284Sobrien size = p->p_vmspace->vm_pmap.pm_stats.resident_count; 104052284Sobrien /* 104118334Speter * if the this process is bigger than the biggest one 104290075Sobrien * remember it. 104352284Sobrien */ 104452284Sobrien if (size > bigsize) { 104518334Speter bigproc = p; 104652284Sobrien bigsize = size; 104790075Sobrien } 104818334Speter } 104952284Sobrien if (bigproc != NULL) { 105052284Sobrien killproc(bigproc, "out of swap space"); 105118334Speter bigproc->p_estcpu = 0; 105252284Sobrien bigproc->p_nice = PRIO_MIN; 105352284Sobrien resetpriority(bigproc); 105490075Sobrien wakeup(&cnt.v_free_count); 105590075Sobrien } 105652284Sobrien } 105718334Speter return force_wakeup; 105852284Sobrien} 105952284Sobrien 106052284Sobrien/* 106152284Sobrien * This routine tries to maintain the pseudo LRU active queue, 106252284Sobrien * so that during long periods of time where there is no paging, 106352284Sobrien * that some statistic accumlation still occurs. This code 106452284Sobrien * helps the situation where paging just starts to occur. 106552284Sobrien */ 106652284Sobrienstatic void 106752284Sobrienvm_pageout_page_stats() 106852284Sobrien{ 106952284Sobrien int s; 107052284Sobrien vm_page_t m,next; 107152284Sobrien int pcount,tpcount; /* Number of pages to check */ 107252284Sobrien static int fullintervalcount = 0; 107352284Sobrien 107452284Sobrien pcount = cnt.v_active_count; 107552284Sobrien fullintervalcount += vm_pageout_stats_interval; 107652284Sobrien if (fullintervalcount < vm_pageout_full_stats_interval) { 107752284Sobrien tpcount = (vm_pageout_stats_max * cnt.v_active_count) / cnt.v_page_count; 107852284Sobrien if (pcount > tpcount) 107952284Sobrien pcount = tpcount; 108090075Sobrien } 108190075Sobrien 108290075Sobrien m = TAILQ_FIRST(&vm_page_queue_active); 108390075Sobrien while ((m != NULL) && (pcount-- > 0)) { 108490075Sobrien int actcount; 108590075Sobrien 108690075Sobrien if (m->queue != PQ_ACTIVE) { 108790075Sobrien break; 108890075Sobrien } 108990075Sobrien 109052284Sobrien next = TAILQ_NEXT(m, pageq); 109152284Sobrien /* 109218334Speter * Don't deactivate pages that are busy. 109352284Sobrien */ 109452284Sobrien if ((m->busy != 0) || 109552284Sobrien (m->flags & PG_BUSY) || 109618334Speter (m->hold_count != 0)) { 109752284Sobrien s = splvm(); 109852284Sobrien TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 109952284Sobrien TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 110018334Speter splx(s); 110152284Sobrien m = next; 110252284Sobrien continue; 110352284Sobrien } 110418334Speter 110552284Sobrien actcount = 0; 110652284Sobrien if (m->flags & PG_REFERENCED) { 110752284Sobrien m->flags &= ~PG_REFERENCED; 110890075Sobrien actcount += 1; 110918334Speter } 111052284Sobrien 111118334Speter actcount += pmap_ts_referenced(VM_PAGE_TO_PHYS(m)); 111252284Sobrien if (actcount) { 111352284Sobrien m->act_count += ACT_ADVANCE + actcount; 111418334Speter if (m->act_count > ACT_MAX) 111552284Sobrien m->act_count = ACT_MAX; 111652284Sobrien s = splvm(); 111752284Sobrien TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 111818334Speter TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 111952284Sobrien splx(s); 112052284Sobrien } else { 112152284Sobrien if (m->act_count == 0) { 112252284Sobrien /* 112352284Sobrien * We turn off page access, so that we have more accurate 112418334Speter * RSS stats. We don't do this in the normal page deactivation 112552284Sobrien * when the system is loaded VM wise, because the cost of 112652284Sobrien * the large number of page protect operations would be higher 112752284Sobrien * than the value of doing the operation. 112852284Sobrien */ 112918334Speter vm_page_protect(m, VM_PROT_NONE); 113052284Sobrien vm_page_deactivate(m); 113152284Sobrien } else { 113252284Sobrien m->act_count -= min(m->act_count, ACT_DECLINE); 113318334Speter s = splvm(); 113490075Sobrien TAILQ_REMOVE(&vm_page_queue_active, m, pageq); 113552284Sobrien TAILQ_INSERT_TAIL(&vm_page_queue_active, m, pageq); 113618334Speter splx(s); 113752284Sobrien } 113852284Sobrien } 113952284Sobrien 114052284Sobrien m = next; 114118334Speter } 114252284Sobrien} 114352284Sobrien 114452284Sobrienstatic int 114552284Sobrienvm_pageout_free_page_calc(count) 114618334Spetervm_size_t count; 114752284Sobrien{ 114852284Sobrien if (count < cnt.v_page_count) 114952284Sobrien return 0; 115018334Speter /* 115152284Sobrien * free_reserved needs to include enough for the largest swap pager 115252284Sobrien * structures plus enough for any pv_entry structs when paging. 115318334Speter */ 115452284Sobrien if (cnt.v_page_count > 1024) 115552284Sobrien cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200; 115618334Speter else 115752284Sobrien cnt.v_free_min = 4; 115852284Sobrien cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE + 115952284Sobrien cnt.v_interrupt_free_min; 116052284Sobrien cnt.v_free_reserved = vm_pageout_page_count + 116152284Sobrien cnt.v_pageout_free_min + (count / 768) + PQ_L2_SIZE; 116290075Sobrien cnt.v_free_min += cnt.v_free_reserved; 116390075Sobrien return 1; 116452284Sobrien} 116552284Sobrien 116690075Sobrien 116790075Sobrien/* 116890075Sobrien * vm_pageout is the high level pageout daemon. 116990075Sobrien */ 117090075Sobrienstatic void 117190075Sobrienvm_pageout() 117290075Sobrien{ 117390075Sobrien /* 117452284Sobrien * Initialize some paging parameters. 117552284Sobrien */ 117652284Sobrien 117752284Sobrien cnt.v_interrupt_free_min = 2; 117852284Sobrien if (cnt.v_page_count < 2000) 117918334Speter vm_pageout_page_count = 8; 118052284Sobrien 118152284Sobrien vm_pageout_free_page_calc(cnt.v_page_count); 118252284Sobrien /* 118352284Sobrien * free_reserved needs to include enough for the largest swap pager 118418334Speter * structures plus enough for any pv_entry structs when paging. 118590075Sobrien */ 118690075Sobrien if (cnt.v_free_count > 6144) 118790075Sobrien cnt.v_free_target = 3 * cnt.v_free_min + cnt.v_free_reserved; 118890075Sobrien else 118990075Sobrien cnt.v_free_target = 2 * cnt.v_free_min + cnt.v_free_reserved; 119090075Sobrien 119118334Speter if (cnt.v_free_count > 2048) { 119252284Sobrien cnt.v_cache_min = cnt.v_free_target; 119390075Sobrien cnt.v_cache_max = 2 * cnt.v_cache_min; 119452284Sobrien cnt.v_inactive_target = (3 * cnt.v_free_target) / 2; 119552284Sobrien } else { 119618334Speter cnt.v_cache_min = 0; 119790075Sobrien cnt.v_cache_max = 0; 119890075Sobrien cnt.v_inactive_target = cnt.v_free_count / 4; 119990075Sobrien } 120090075Sobrien if (cnt.v_inactive_target > cnt.v_free_count / 3) 120190075Sobrien cnt.v_inactive_target = cnt.v_free_count / 3; 120252284Sobrien 120390075Sobrien /* XXX does not really belong here */ 120490075Sobrien if (vm_page_max_wired == 0) 120590075Sobrien vm_page_max_wired = cnt.v_free_count / 3; 120690075Sobrien 120790075Sobrien if (vm_pageout_stats_max == 0) 120890075Sobrien vm_pageout_stats_max = cnt.v_free_target; 120952284Sobrien 121090075Sobrien /* 121152284Sobrien * Set interval in seconds for stats scan. 121252284Sobrien */ 121318334Speter if (vm_pageout_stats_interval == 0) 121452284Sobrien vm_pageout_stats_interval = 4; 121552284Sobrien if (vm_pageout_full_stats_interval == 0) 121652284Sobrien vm_pageout_full_stats_interval = vm_pageout_stats_interval * 4; 121752284Sobrien 121852284Sobrien 121952284Sobrien /* 122052284Sobrien * Set maximum free per pass 122152284Sobrien */ 122252284Sobrien if (vm_pageout_stats_free_max == 0) 122352284Sobrien vm_pageout_stats_free_max = 25; 122452284Sobrien 122552284Sobrien max_page_launder = (cnt.v_page_count > 1800 ? 32 : 16); 122618334Speter 122752284Sobrien swap_pager_swap_init(); 122852284Sobrien /* 122952284Sobrien * The pageout daemon is never done, so loop forever. 123018334Speter */ 123152284Sobrien while (TRUE) { 123252284Sobrien int inactive_target; 123352284Sobrien int error; 123418334Speter int s = splvm(); 123552284Sobrien if (!vm_pages_needed || 123652284Sobrien ((cnt.v_free_count + cnt.v_cache_count) > cnt.v_free_min)) { 123752284Sobrien vm_pages_needed = 0; 123852284Sobrien error = tsleep(&vm_pages_needed, 123952284Sobrien PVM, "psleep", vm_pageout_stats_interval * hz); 124090075Sobrien if (error && !vm_pages_needed) { 124190075Sobrien splx(s); 124252284Sobrien vm_pageout_page_stats(); 124352284Sobrien continue; 124452284Sobrien } 124518334Speter } else if (vm_pages_needed) { 124652284Sobrien vm_pages_needed = 0; 124790075Sobrien tsleep(&vm_pages_needed, PVM, "psleep", hz/2); 124852284Sobrien } 124952284Sobrien 125052284Sobrien if (vm_pages_needed) 125152284Sobrien cnt.v_pdwakeups++; 125252284Sobrien vm_pages_needed = 0; 125352284Sobrien splx(s); 125452284Sobrien vm_pager_sync(); 125552284Sobrien vm_pageout_scan(); 125618334Speter vm_pageout_deficit = 0; 125752284Sobrien vm_pager_sync(); 125852284Sobrien wakeup(&cnt.v_free_count); 125952284Sobrien } 126052284Sobrien} 126152284Sobrien 126252284Sobrienvoid 126352284Sobrienpagedaemon_wakeup() 126418334Speter{ 126552284Sobrien if (!vm_pages_needed && curproc != pageproc) { 126652284Sobrien vm_pages_needed++; 126752284Sobrien wakeup(&vm_pages_needed); 126852284Sobrien } 126918334Speter} 127052284Sobrien 127152284Sobrien#if !defined(NO_SWAPPING) 127252284Sobrienstatic void 127352284Sobrienvm_req_vmdaemon() 127452284Sobrien{ 127552284Sobrien static int lastrun = 0; 127652284Sobrien 127718334Speter if ((ticks > (lastrun + hz)) || (ticks < lastrun)) { 127852284Sobrien wakeup(&vm_daemon_needed); 127952284Sobrien lastrun = ticks; 128052284Sobrien } 128118334Speter} 128252284Sobrien 128352284Sobrienstatic void 128452284Sobrienvm_daemon() 128590075Sobrien{ 128618334Speter vm_object_t object; 128796263Sobrien struct proc *p; 128896263Sobrien 128996263Sobrien while (TRUE) { 129096263Sobrien tsleep(&vm_daemon_needed, PUSER, "psleep", 0); 129196263Sobrien if (vm_pageout_req_swapout) { 129252284Sobrien swapout_procs(vm_pageout_req_swapout); 129352284Sobrien vm_pageout_req_swapout = 0; 129418334Speter } 129552284Sobrien /* 129652284Sobrien * scan the processes for exceeding their rlimits or if 129752284Sobrien * process is swapped out -- deactivate pages 129852284Sobrien */ 129952284Sobrien 130052284Sobrien for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 130190075Sobrien quad_t limit; 130252284Sobrien vm_offset_t size; 130352284Sobrien 130452284Sobrien /* 130552284Sobrien * if this is a system process or if we have already 130690075Sobrien * looked at this process, skip it. 130752284Sobrien */ 130852284Sobrien if (p->p_flag & (P_SYSTEM | P_WEXIT)) { 130918334Speter continue; 131052284Sobrien } 131152284Sobrien /* 131252284Sobrien * if the process is in a non-running type state, 131352284Sobrien * don't touch it. 131452284Sobrien */ 131518334Speter if (p->p_stat != SRUN && p->p_stat != SSLEEP) { 131690075Sobrien continue; 131752284Sobrien } 131852284Sobrien /* 131952284Sobrien * get a limit 132052284Sobrien */ 132152284Sobrien limit = qmin(p->p_rlimit[RLIMIT_RSS].rlim_cur, 132218334Speter p->p_rlimit[RLIMIT_RSS].rlim_max); 132352284Sobrien 132452284Sobrien /* 132518334Speter * let processes that are swapped out really be 132652284Sobrien * swapped out set the limit to nothing (will force a 132752284Sobrien * swap-out.) 132852284Sobrien */ 132952284Sobrien if ((p->p_flag & P_INMEM) == 0) 133052284Sobrien limit = 0; /* XXX */ 133152284Sobrien 133252284Sobrien size = p->p_vmspace->vm_pmap.pm_stats.resident_count * PAGE_SIZE; 133318334Speter if (limit >= 0 && size >= limit) { 133452284Sobrien vm_pageout_map_deactivate_pages(&p->p_vmspace->vm_map, 133590075Sobrien (vm_pindex_t)(limit >> PAGE_SHIFT) ); 133652284Sobrien } 133718334Speter } 133852284Sobrien } 133952284Sobrien} 134052284Sobrien#endif 134190075Sobrien