1df8bae1dSRodney W. Grimes /* 2df8bae1dSRodney W. Grimes * Copyright (c) 1991, 1993 3df8bae1dSRodney W. Grimes * The Regents of the University of California. All rights reserved. 4df8bae1dSRodney W. Grimes * 5df8bae1dSRodney W. Grimes * This code is derived from software contributed to Berkeley by 6df8bae1dSRodney W. Grimes * The Mach Operating System project at Carnegie-Mellon University. 7df8bae1dSRodney W. Grimes * 8df8bae1dSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 9df8bae1dSRodney W. Grimes * modification, are permitted provided that the following conditions 10df8bae1dSRodney W. Grimes * are met: 11df8bae1dSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 12df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 13df8bae1dSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 14df8bae1dSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 15df8bae1dSRodney W. Grimes * documentation and/or other materials provided with the distribution. 16df8bae1dSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 17df8bae1dSRodney W. Grimes * must display the following acknowledgement: 18df8bae1dSRodney W. Grimes * This product includes software developed by the University of 19df8bae1dSRodney W. Grimes * California, Berkeley and its contributors. 20df8bae1dSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 21df8bae1dSRodney W. Grimes * may be used to endorse or promote products derived from this software 22df8bae1dSRodney W. Grimes * without specific prior written permission. 23df8bae1dSRodney W. Grimes * 24df8bae1dSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25df8bae1dSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26df8bae1dSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27df8bae1dSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28df8bae1dSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29df8bae1dSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30df8bae1dSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31df8bae1dSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32df8bae1dSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33df8bae1dSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34df8bae1dSRodney W. Grimes * SUCH DAMAGE. 35df8bae1dSRodney W. Grimes * 363c4dd356SDavid Greenman * from: @(#)vm_object.c 8.5 (Berkeley) 3/22/94 37df8bae1dSRodney W. Grimes * 38df8bae1dSRodney W. Grimes * 39df8bae1dSRodney W. Grimes * Copyright (c) 1987, 1990 Carnegie-Mellon University. 40df8bae1dSRodney W. Grimes * All rights reserved. 41df8bae1dSRodney W. Grimes * 42df8bae1dSRodney W. Grimes * Authors: Avadis Tevanian, Jr., Michael Wayne Young 43df8bae1dSRodney W. Grimes * 44df8bae1dSRodney W. Grimes * Permission to use, copy, modify and distribute this software and 45df8bae1dSRodney W. Grimes * its documentation is hereby granted, provided that both the copyright 46df8bae1dSRodney W. Grimes * notice and this permission notice appear in all copies of the 47df8bae1dSRodney W. Grimes * software, derivative works or modified versions, and any portions 48df8bae1dSRodney W. Grimes * thereof, and that both notices appear in supporting documentation. 49df8bae1dSRodney W. Grimes * 50df8bae1dSRodney W. Grimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 51df8bae1dSRodney W. Grimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 52df8bae1dSRodney W. Grimes * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 53df8bae1dSRodney W. Grimes * 54df8bae1dSRodney W. Grimes * Carnegie Mellon requests users of this software to return to 55df8bae1dSRodney W. Grimes * 56df8bae1dSRodney W. Grimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 57df8bae1dSRodney W. Grimes * School of Computer Science 58df8bae1dSRodney W. Grimes * Carnegie Mellon University 59df8bae1dSRodney W. Grimes * Pittsburgh PA 15213-3890 60df8bae1dSRodney W. Grimes * 61df8bae1dSRodney W. Grimes * any improvements or extensions that they make and grant Carnegie the 62df8bae1dSRodney W. Grimes * rights to redistribute these changes. 633c4dd356SDavid Greenman * 641efb74fbSJohn Dyson * $Id: vm_object.c,v 1.101 1997/11/18 11:02:19 bde Exp $ 65df8bae1dSRodney W. Grimes */ 66df8bae1dSRodney W. Grimes 67df8bae1dSRodney W. Grimes /* 68df8bae1dSRodney W. Grimes * Virtual memory object module. 69df8bae1dSRodney W. Grimes */ 70df8bae1dSRodney W. Grimes 71df8bae1dSRodney W. Grimes #include <sys/param.h> 72df8bae1dSRodney W. Grimes #include <sys/systm.h> 73f23b4c91SGarrett Wollman #include <sys/proc.h> /* for curproc, pageproc */ 740d94caffSDavid Greenman #include <sys/vnode.h> 75efeaf95aSDavid Greenman #include <sys/vmmeter.h> 76867a482dSJohn Dyson #include <sys/mman.h> 77df8bae1dSRodney W. Grimes 78df8bae1dSRodney W. Grimes #include <vm/vm.h> 79efeaf95aSDavid Greenman #include <vm/vm_param.h> 80efeaf95aSDavid Greenman #include <vm/vm_prot.h> 81996c772fSJohn Dyson #include <sys/lock.h> 82efeaf95aSDavid Greenman #include <vm/pmap.h> 83efeaf95aSDavid Greenman #include <vm/vm_map.h> 84efeaf95aSDavid Greenman #include <vm/vm_object.h> 85df8bae1dSRodney W. Grimes #include <vm/vm_page.h> 8626f9a767SRodney W. Grimes #include <vm/vm_pageout.h> 870d94caffSDavid Greenman #include <vm/vm_pager.h> 8805f0fdd2SPoul-Henning Kamp #include <vm/swap_pager.h> 89a1f6d91cSDavid Greenman #include <vm/vm_kern.h> 90efeaf95aSDavid Greenman #include <vm/vm_extern.h> 9199448ed1SJohn Dyson #include <vm/vm_zone.h> 9226f9a767SRodney W. Grimes 93cac597e4SBruce Evans static void vm_object_qcollapse __P((vm_object_t object)); 94f708ef1bSPoul-Henning Kamp #ifdef not_used 95f708ef1bSPoul-Henning Kamp static void vm_object_deactivate_pages __P((vm_object_t)); 96f708ef1bSPoul-Henning Kamp #endif 97f708ef1bSPoul-Henning Kamp static void vm_object_terminate __P((vm_object_t)); 98f708ef1bSPoul-Henning Kamp static void vm_object_cache_trim __P((void)); 99f6b04d2bSDavid Greenman 100df8bae1dSRodney W. Grimes /* 101df8bae1dSRodney W. Grimes * Virtual memory objects maintain the actual data 102df8bae1dSRodney W. Grimes * associated with allocated virtual memory. A given 103df8bae1dSRodney W. Grimes * page of memory exists within exactly one object. 104df8bae1dSRodney W. Grimes * 105df8bae1dSRodney W. Grimes * An object is only deallocated when all "references" 106df8bae1dSRodney W. Grimes * are given up. Only one "reference" to a given 107df8bae1dSRodney W. Grimes * region of an object should be writeable. 108df8bae1dSRodney W. Grimes * 109df8bae1dSRodney W. Grimes * Associated with each object is a list of all resident 110df8bae1dSRodney W. Grimes * memory pages belonging to that object; this list is 111df8bae1dSRodney W. Grimes * maintained by the "vm_page" module, and locked by the object's 112df8bae1dSRodney W. Grimes * lock. 113df8bae1dSRodney W. Grimes * 114df8bae1dSRodney W. Grimes * Each object also records a "pager" routine which is 115df8bae1dSRodney W. Grimes * used to retrieve (and store) pages to the proper backing 116df8bae1dSRodney W. Grimes * storage. In addition, objects may be backed by other 117df8bae1dSRodney W. Grimes * objects from which they were virtual-copied. 118df8bae1dSRodney W. Grimes * 119df8bae1dSRodney W. Grimes * The only items within the object structure which are 120df8bae1dSRodney W. Grimes * modified after time of creation are: 121df8bae1dSRodney W. Grimes * reference count locked by object's lock 122df8bae1dSRodney W. Grimes * pager routine locked by object's lock 123df8bae1dSRodney W. Grimes * 124df8bae1dSRodney W. Grimes */ 125df8bae1dSRodney W. Grimes 12628f8db14SBruce Evans int vm_object_cache_max; 12728f8db14SBruce Evans struct object_q vm_object_cached_list; 1284de628deSBruce Evans static int vm_object_cached; /* size of cached list */ 12928f8db14SBruce Evans struct object_q vm_object_list; 130996c772fSJohn Dyson struct simplelock vm_object_list_lock; 1314de628deSBruce Evans static long vm_object_count; /* count of all objects */ 13228f8db14SBruce Evans vm_object_t kernel_object; 13328f8db14SBruce Evans vm_object_t kmem_object; 134f708ef1bSPoul-Henning Kamp static struct vm_object kernel_object_store; 135f708ef1bSPoul-Henning Kamp static struct vm_object kmem_object_store; 136aef922f5SJohn Dyson extern int vm_pageout_page_count; 137df8bae1dSRodney W. Grimes 138f708ef1bSPoul-Henning Kamp static long object_collapses; 139f708ef1bSPoul-Henning Kamp static long object_bypasses; 1405070c7f8SJohn Dyson static int next_index; 14199448ed1SJohn Dyson static vm_zone_t obj_zone; 14299448ed1SJohn Dyson static struct vm_zone obj_zone_store; 14399448ed1SJohn Dyson #define VM_OBJECTS_INIT 256 14499448ed1SJohn Dyson struct vm_object vm_objects_init[VM_OBJECTS_INIT]; 145df8bae1dSRodney W. Grimes 1463075778bSJohn Dyson void 14724a1cce3SDavid Greenman _vm_object_allocate(type, size, object) 14824a1cce3SDavid Greenman objtype_t type; 149df8bae1dSRodney W. Grimes vm_size_t size; 150df8bae1dSRodney W. Grimes register vm_object_t object; 151df8bae1dSRodney W. Grimes { 15299448ed1SJohn Dyson int incr; 153df8bae1dSRodney W. Grimes TAILQ_INIT(&object->memq); 15424a1cce3SDavid Greenman TAILQ_INIT(&object->shadow_head); 155a1f6d91cSDavid Greenman 15624a1cce3SDavid Greenman object->type = type; 157df8bae1dSRodney W. Grimes object->size = size; 158a1f6d91cSDavid Greenman object->ref_count = 1; 15924a1cce3SDavid Greenman object->flags = 0; 160867a482dSJohn Dyson object->behavior = OBJ_NORMAL; 161df8bae1dSRodney W. Grimes object->paging_in_progress = 0; 162a1f6d91cSDavid Greenman object->resident_page_count = 0; 163de5f6a77SJohn Dyson object->shadow_count = 0; 1645070c7f8SJohn Dyson object->pg_color = next_index; 16599448ed1SJohn Dyson if ( size > (PQ_L2_SIZE / 3 + PQ_PRIME1)) 16699448ed1SJohn Dyson incr = PQ_L2_SIZE / 3 + PQ_PRIME1; 16799448ed1SJohn Dyson else 16899448ed1SJohn Dyson incr = size; 16999448ed1SJohn Dyson next_index = (next_index + incr) & PQ_L2_MASK; 17024a1cce3SDavid Greenman object->handle = NULL; 171a316d390SJohn Dyson object->paging_offset = (vm_ooffset_t) 0; 17224a1cce3SDavid Greenman object->backing_object = NULL; 173a316d390SJohn Dyson object->backing_object_offset = (vm_ooffset_t) 0; 174a2f4a846SJohn Dyson object->page_hint = NULL; 175a1f6d91cSDavid Greenman 176a1f6d91cSDavid Greenman object->last_read = 0; 177df8bae1dSRodney W. Grimes 178df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&vm_object_list, object, object_list); 179df8bae1dSRodney W. Grimes vm_object_count++; 180df8bae1dSRodney W. Grimes } 181df8bae1dSRodney W. Grimes 182df8bae1dSRodney W. Grimes /* 18326f9a767SRodney W. Grimes * vm_object_init: 18426f9a767SRodney W. Grimes * 18526f9a767SRodney W. Grimes * Initialize the VM objects module. 18626f9a767SRodney W. Grimes */ 18726f9a767SRodney W. Grimes void 188a316d390SJohn Dyson vm_object_init() 18926f9a767SRodney W. Grimes { 19026f9a767SRodney W. Grimes TAILQ_INIT(&vm_object_cached_list); 19126f9a767SRodney W. Grimes TAILQ_INIT(&vm_object_list); 192996c772fSJohn Dyson simple_lock_init(&vm_object_list_lock); 19326f9a767SRodney W. Grimes vm_object_count = 0; 1940217125fSDavid Greenman 1950217125fSDavid Greenman vm_object_cache_max = 84; 1960217125fSDavid Greenman if (cnt.v_page_count > 1000) 19746268a60SDavid Greenman vm_object_cache_max += (cnt.v_page_count - 1000) / 4; 19826f9a767SRodney W. Grimes 19926f9a767SRodney W. Grimes kernel_object = &kernel_object_store; 200a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 20126f9a767SRodney W. Grimes kernel_object); 20226f9a767SRodney W. Grimes 20326f9a767SRodney W. Grimes kmem_object = &kmem_object_store; 204a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 20526f9a767SRodney W. Grimes kmem_object); 20699448ed1SJohn Dyson 20799448ed1SJohn Dyson obj_zone = &obj_zone_store; 20899448ed1SJohn Dyson zbootinit(obj_zone, "VM OBJECT", sizeof (struct vm_object), 20999448ed1SJohn Dyson vm_objects_init, VM_OBJECTS_INIT); 21099448ed1SJohn Dyson } 21199448ed1SJohn Dyson 21299448ed1SJohn Dyson void 21399448ed1SJohn Dyson vm_object_init2() { 2140a80f406SJohn Dyson zinitna(obj_zone, NULL, NULL, 0, 0, 0, 1); 21526f9a767SRodney W. Grimes } 21626f9a767SRodney W. Grimes 21726f9a767SRodney W. Grimes /* 21826f9a767SRodney W. Grimes * vm_object_allocate: 21926f9a767SRodney W. Grimes * 22026f9a767SRodney W. Grimes * Returns a new object with the given size. 22126f9a767SRodney W. Grimes */ 22226f9a767SRodney W. Grimes 22326f9a767SRodney W. Grimes vm_object_t 22424a1cce3SDavid Greenman vm_object_allocate(type, size) 22524a1cce3SDavid Greenman objtype_t type; 22626f9a767SRodney W. Grimes vm_size_t size; 22726f9a767SRodney W. Grimes { 22826f9a767SRodney W. Grimes register vm_object_t result; 22999448ed1SJohn Dyson result = (vm_object_t) zalloc(obj_zone); 23067bf6868SJohn Dyson 23124a1cce3SDavid Greenman _vm_object_allocate(type, size, result); 23226f9a767SRodney W. Grimes 23326f9a767SRodney W. Grimes return (result); 23426f9a767SRodney W. Grimes } 23526f9a767SRodney W. Grimes 23626f9a767SRodney W. Grimes 23726f9a767SRodney W. Grimes /* 238df8bae1dSRodney W. Grimes * vm_object_reference: 239df8bae1dSRodney W. Grimes * 240df8bae1dSRodney W. Grimes * Gets another reference to the given object. 241df8bae1dSRodney W. Grimes */ 2426476c0d2SJohn Dyson void 24326f9a767SRodney W. Grimes vm_object_reference(object) 244df8bae1dSRodney W. Grimes register vm_object_t object; 245df8bae1dSRodney W. Grimes { 246df8bae1dSRodney W. Grimes if (object == NULL) 247df8bae1dSRodney W. Grimes return; 248df8bae1dSRodney W. Grimes 24924a1cce3SDavid Greenman if (object->ref_count == 0) { 25024a1cce3SDavid Greenman if ((object->flags & OBJ_CANPERSIST) == 0) 25124a1cce3SDavid Greenman panic("vm_object_reference: non-persistent object with 0 ref_count"); 25224a1cce3SDavid Greenman TAILQ_REMOVE(&vm_object_cached_list, object, cached_list); 25324a1cce3SDavid Greenman vm_object_cached--; 25424a1cce3SDavid Greenman } 255df8bae1dSRodney W. Grimes object->ref_count++; 256df8bae1dSRodney W. Grimes } 257df8bae1dSRodney W. Grimes 258df8bae1dSRodney W. Grimes /* 259df8bae1dSRodney W. Grimes * vm_object_deallocate: 260df8bae1dSRodney W. Grimes * 261df8bae1dSRodney W. Grimes * Release a reference to the specified object, 262df8bae1dSRodney W. Grimes * gained either through a vm_object_allocate 263df8bae1dSRodney W. Grimes * or a vm_object_reference call. When all references 264df8bae1dSRodney W. Grimes * are gone, storage associated with this object 265df8bae1dSRodney W. Grimes * may be relinquished. 266df8bae1dSRodney W. Grimes * 267df8bae1dSRodney W. Grimes * No object may be locked. 268df8bae1dSRodney W. Grimes */ 26926f9a767SRodney W. Grimes void 27026f9a767SRodney W. Grimes vm_object_deallocate(object) 27126f9a767SRodney W. Grimes vm_object_t object; 272df8bae1dSRodney W. Grimes { 273df8bae1dSRodney W. Grimes vm_object_t temp; 274df8bae1dSRodney W. Grimes 275df8bae1dSRodney W. Grimes while (object != NULL) { 276df8bae1dSRodney W. Grimes 277ba8da839SDavid Greenman if (object->ref_count == 0) 278ba8da839SDavid Greenman panic("vm_object_deallocate: object deallocated too many times"); 279ba8da839SDavid Greenman 280df8bae1dSRodney W. Grimes /* 281df8bae1dSRodney W. Grimes * Lose the reference 282df8bae1dSRodney W. Grimes */ 283be6d5bfaSDavid Greenman object->ref_count--; 284be6d5bfaSDavid Greenman if (object->ref_count != 0) { 285be6d5bfaSDavid Greenman if ((object->ref_count == 1) && 28624a1cce3SDavid Greenman (object->handle == NULL) && 28724a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || 28824a1cce3SDavid Greenman object->type == OBJT_SWAP)) { 289a1f6d91cSDavid Greenman vm_object_t robject; 290b18bfc3dSJohn Dyson robject = TAILQ_FIRST(&object->shadow_head); 291be6d5bfaSDavid Greenman if ((robject != NULL) && 29224a1cce3SDavid Greenman (robject->handle == NULL) && 29324a1cce3SDavid Greenman (robject->type == OBJT_DEFAULT || 29424a1cce3SDavid Greenman robject->type == OBJT_SWAP)) { 295a1f6d91cSDavid Greenman int s; 296a1f6d91cSDavid Greenman robject->ref_count += 2; 2979b4814bbSDavid Greenman object->ref_count += 2; 298a1f6d91cSDavid Greenman 299a1f6d91cSDavid Greenman do { 300b18bfc3dSJohn Dyson s = splvm(); 301a1f6d91cSDavid Greenman while (robject->paging_in_progress) { 302c0503609SDavid Greenman robject->flags |= OBJ_PIPWNT; 303a1f6d91cSDavid Greenman tsleep(robject, PVM, "objde1", 0); 3040d94caffSDavid Greenman } 305a1f6d91cSDavid Greenman 306a1f6d91cSDavid Greenman while (object->paging_in_progress) { 307c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 308a1f6d91cSDavid Greenman tsleep(object, PVM, "objde2", 0); 309a1f6d91cSDavid Greenman } 310a1f6d91cSDavid Greenman splx(s); 311a1f6d91cSDavid Greenman 312a1f6d91cSDavid Greenman } while( object->paging_in_progress || robject->paging_in_progress); 313a1f6d91cSDavid Greenman 3149b4814bbSDavid Greenman object->ref_count -= 2; 315a1f6d91cSDavid Greenman robject->ref_count -= 2; 316a1f6d91cSDavid Greenman if( robject->ref_count == 0) { 317a1f6d91cSDavid Greenman robject->ref_count += 1; 318ba8da839SDavid Greenman object = robject; 319ba8da839SDavid Greenman continue; 320a1f6d91cSDavid Greenman } 321a1f6d91cSDavid Greenman vm_object_collapse(robject); 322a1f6d91cSDavid Greenman return; 323010cf3b9SDavid Greenman } 324010cf3b9SDavid Greenman } 325df8bae1dSRodney W. Grimes /* 3260d94caffSDavid Greenman * If there are still references, then we are done. 327df8bae1dSRodney W. Grimes */ 328df8bae1dSRodney W. Grimes return; 329df8bae1dSRodney W. Grimes } 330df8bae1dSRodney W. Grimes 33124a1cce3SDavid Greenman if (object->type == OBJT_VNODE) { 33224a1cce3SDavid Greenman struct vnode *vp = object->handle; 333f5cf85d4SDavid Greenman 33424a1cce3SDavid Greenman vp->v_flag &= ~VTEXT; 335f5cf85d4SDavid Greenman } 336f5cf85d4SDavid Greenman 337f919ebdeSDavid Greenman /* 338f919ebdeSDavid Greenman * See if this object can persist and has some resident 339f919ebdeSDavid Greenman * pages. If so, enter it in the cache. 340f919ebdeSDavid Greenman */ 341f5cf85d4SDavid Greenman if (object->flags & OBJ_CANPERSIST) { 342f5cf85d4SDavid Greenman if (object->resident_page_count != 0) { 3436476c0d2SJohn Dyson #if 0 34424a1cce3SDavid Greenman vm_object_page_clean(object, 0, 0 ,TRUE, TRUE); 3456476c0d2SJohn Dyson #endif 346df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&vm_object_cached_list, object, 347df8bae1dSRodney W. Grimes cached_list); 348df8bae1dSRodney W. Grimes vm_object_cached++; 349df8bae1dSRodney W. Grimes 350df8bae1dSRodney W. Grimes vm_object_cache_trim(); 351df8bae1dSRodney W. Grimes return; 352f5cf85d4SDavid Greenman } else { 353f5cf85d4SDavid Greenman object->flags &= ~OBJ_CANPERSIST; 354f5cf85d4SDavid Greenman } 355df8bae1dSRodney W. Grimes } 356f919ebdeSDavid Greenman 357df8bae1dSRodney W. Grimes /* 35824a1cce3SDavid Greenman * Make sure no one uses us. 359df8bae1dSRodney W. Grimes */ 3600d94caffSDavid Greenman object->flags |= OBJ_DEAD; 361df8bae1dSRodney W. Grimes 3621efb74fbSJohn Dyson if (object->type == OBJT_VNODE) { 3631efb74fbSJohn Dyson struct vnode *vp = object->handle; 3641efb74fbSJohn Dyson if (vp->v_flag & VVMIO) { 3651efb74fbSJohn Dyson object->ref_count++; 3661efb74fbSJohn Dyson vm_freeze_copyopts(object, 0, object->size); 3671efb74fbSJohn Dyson object->ref_count--; 3681efb74fbSJohn Dyson } 3691efb74fbSJohn Dyson } 3701efb74fbSJohn Dyson 37124a1cce3SDavid Greenman temp = object->backing_object; 372de5f6a77SJohn Dyson if (temp) { 37324a1cce3SDavid Greenman TAILQ_REMOVE(&temp->shadow_head, object, shadow_list); 374de5f6a77SJohn Dyson --temp->shadow_count; 375de5f6a77SJohn Dyson } 376df8bae1dSRodney W. Grimes vm_object_terminate(object); 377df8bae1dSRodney W. Grimes /* unlocks and deallocates object */ 378df8bae1dSRodney W. Grimes object = temp; 379df8bae1dSRodney W. Grimes } 380df8bae1dSRodney W. Grimes } 381df8bae1dSRodney W. Grimes 382df8bae1dSRodney W. Grimes /* 383df8bae1dSRodney W. Grimes * vm_object_terminate actually destroys the specified object, freeing 384df8bae1dSRodney W. Grimes * up all previously used resources. 385df8bae1dSRodney W. Grimes * 386df8bae1dSRodney W. Grimes * The object must be locked. 387df8bae1dSRodney W. Grimes */ 388f708ef1bSPoul-Henning Kamp static void 38926f9a767SRodney W. Grimes vm_object_terminate(object) 390df8bae1dSRodney W. Grimes register vm_object_t object; 391df8bae1dSRodney W. Grimes { 3923af76890SPoul-Henning Kamp register vm_page_t p; 39326f9a767SRodney W. Grimes int s; 394df8bae1dSRodney W. Grimes 3953c631446SJohn Dyson if (object->flags & OBJ_VFS_REF) 3963c631446SJohn Dyson panic("vm_object_deallocate: freeing VFS_REF'ed object"); 3973c631446SJohn Dyson 398df8bae1dSRodney W. Grimes /* 399f6b04d2bSDavid Greenman * wait for the pageout daemon to be done with the object 400df8bae1dSRodney W. Grimes */ 401b18bfc3dSJohn Dyson s = splvm(); 402df8bae1dSRodney W. Grimes while (object->paging_in_progress) { 403c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 40424a1cce3SDavid Greenman tsleep(object, PVM, "objtrm", 0); 405df8bae1dSRodney W. Grimes } 4060d94caffSDavid Greenman splx(s); 407df8bae1dSRodney W. Grimes 40826f9a767SRodney W. Grimes if (object->paging_in_progress != 0) 40926f9a767SRodney W. Grimes panic("vm_object_deallocate: pageout in progress"); 41026f9a767SRodney W. Grimes 41126f9a767SRodney W. Grimes /* 4120d94caffSDavid Greenman * Clean and free the pages, as appropriate. All references to the 4130d94caffSDavid Greenman * object are gone, so we don't need to lock it. 41426f9a767SRodney W. Grimes */ 41524a1cce3SDavid Greenman if (object->type == OBJT_VNODE) { 41624a1cce3SDavid Greenman struct vnode *vp = object->handle; 4170abc78a6SPoul-Henning Kamp struct proc *cp = curproc; /* XXX */ 4186476c0d2SJohn Dyson int waslocked; 419f6b04d2bSDavid Greenman 4206476c0d2SJohn Dyson waslocked = VOP_ISLOCKED(vp); 4216476c0d2SJohn Dyson if (!waslocked) 4220abc78a6SPoul-Henning Kamp vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, cp); 42324a1cce3SDavid Greenman vm_object_page_clean(object, 0, 0, TRUE, FALSE); 424f6b04d2bSDavid Greenman vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); 4256476c0d2SJohn Dyson if (!waslocked) 4260abc78a6SPoul-Henning Kamp VOP_UNLOCK(vp, 0, cp); 427df8bae1dSRodney W. Grimes } 428996c772fSJohn Dyson 4290d94caffSDavid Greenman /* 4300d94caffSDavid Greenman * Now free the pages. For internal objects, this also removes them 4310d94caffSDavid Greenman * from paging queues. 432df8bae1dSRodney W. Grimes */ 433b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&object->memq)) != NULL) { 434a2f4a846SJohn Dyson if (p->busy || (p->flags & PG_BUSY)) 435be6d5bfaSDavid Greenman printf("vm_object_terminate: freeing busy page\n"); 4360d94caffSDavid Greenman PAGE_WAKEUP(p); 437df8bae1dSRodney W. Grimes vm_page_free(p); 438df8bae1dSRodney W. Grimes cnt.v_pfree++; 439df8bae1dSRodney W. Grimes } 440df8bae1dSRodney W. Grimes 441df8bae1dSRodney W. Grimes /* 442df8bae1dSRodney W. Grimes * Let the pager know object is dead. 443df8bae1dSRodney W. Grimes */ 44424a1cce3SDavid Greenman vm_pager_deallocate(object); 445df8bae1dSRodney W. Grimes 446996c772fSJohn Dyson simple_lock(&vm_object_list_lock); 447df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, object, object_list); 448df8bae1dSRodney W. Grimes vm_object_count--; 449996c772fSJohn Dyson simple_unlock(&vm_object_list_lock); 450df8bae1dSRodney W. Grimes 4510426122fSDavid Greenman wakeup(object); 4520426122fSDavid Greenman 453df8bae1dSRodney W. Grimes /* 454df8bae1dSRodney W. Grimes * Free the space for the object. 455df8bae1dSRodney W. Grimes */ 45699448ed1SJohn Dyson zfree(obj_zone, object); 457df8bae1dSRodney W. Grimes } 458df8bae1dSRodney W. Grimes 459df8bae1dSRodney W. Grimes /* 460df8bae1dSRodney W. Grimes * vm_object_page_clean 461df8bae1dSRodney W. Grimes * 462df8bae1dSRodney W. Grimes * Clean all dirty pages in the specified range of object. 46326f9a767SRodney W. Grimes * Leaves page on whatever queue it is currently on. 46426f9a767SRodney W. Grimes * 46526f9a767SRodney W. Grimes * Odd semantics: if start == end, we clean everything. 46626f9a767SRodney W. Grimes * 46726f9a767SRodney W. Grimes * The object must be locked. 46826f9a767SRodney W. Grimes */ 469f6b04d2bSDavid Greenman 470f6b04d2bSDavid Greenman void 47124a1cce3SDavid Greenman vm_object_page_clean(object, start, end, syncio, lockflag) 472f6b04d2bSDavid Greenman vm_object_t object; 473a316d390SJohn Dyson vm_pindex_t start; 474a316d390SJohn Dyson vm_pindex_t end; 475f6b04d2bSDavid Greenman boolean_t syncio; 47624a1cce3SDavid Greenman boolean_t lockflag; 477f6b04d2bSDavid Greenman { 478bd7e5f99SJohn Dyson register vm_page_t p, np, tp; 479f6b04d2bSDavid Greenman register vm_offset_t tstart, tend; 480bd7e5f99SJohn Dyson vm_pindex_t pi; 481aef922f5SJohn Dyson int s; 48224a1cce3SDavid Greenman struct vnode *vp; 483aef922f5SJohn Dyson int runlen; 484bd7e5f99SJohn Dyson int maxf; 485bd7e5f99SJohn Dyson int chkb; 486bd7e5f99SJohn Dyson int maxb; 487bd7e5f99SJohn Dyson int i; 488bd7e5f99SJohn Dyson vm_page_t maf[vm_pageout_page_count]; 489bd7e5f99SJohn Dyson vm_page_t mab[vm_pageout_page_count]; 490aef922f5SJohn Dyson vm_page_t ma[vm_pageout_page_count]; 491996c772fSJohn Dyson struct proc *pproc = curproc; /* XXX */ 492f6b04d2bSDavid Greenman 493aef922f5SJohn Dyson if (object->type != OBJT_VNODE || 494aef922f5SJohn Dyson (object->flags & OBJ_MIGHTBEDIRTY) == 0) 495f6b04d2bSDavid Greenman return; 496f6b04d2bSDavid Greenman 49724a1cce3SDavid Greenman vp = object->handle; 49824a1cce3SDavid Greenman 49924a1cce3SDavid Greenman if (lockflag) 500996c772fSJohn Dyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, pproc); 501aef922f5SJohn Dyson object->flags |= OBJ_CLEANING; 50224a1cce3SDavid Greenman 503f6b04d2bSDavid Greenman tstart = start; 504f6b04d2bSDavid Greenman if (end == 0) { 505f6b04d2bSDavid Greenman tend = object->size; 506f6b04d2bSDavid Greenman } else { 507f6b04d2bSDavid Greenman tend = end; 508f6b04d2bSDavid Greenman } 509a316d390SJohn Dyson if ((tstart == 0) && (tend == object->size)) { 510aef922f5SJohn Dyson object->flags &= ~(OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY); 511ec4f9fb0SDavid Greenman } 512b18bfc3dSJohn Dyson for(p = TAILQ_FIRST(&object->memq); p; p = TAILQ_NEXT(p, listq)) 513bd7e5f99SJohn Dyson p->flags |= PG_CLEANCHK; 514f6b04d2bSDavid Greenman 515bd7e5f99SJohn Dyson rescan: 516b18bfc3dSJohn Dyson for(p = TAILQ_FIRST(&object->memq); p; p = np) { 517b18bfc3dSJohn Dyson np = TAILQ_NEXT(p, listq); 518bd7e5f99SJohn Dyson 519bd7e5f99SJohn Dyson pi = p->pindex; 520bd7e5f99SJohn Dyson if (((p->flags & PG_CLEANCHK) == 0) || 521bd7e5f99SJohn Dyson (pi < tstart) || (pi >= tend) || 5225070c7f8SJohn Dyson (p->valid == 0) || 5235070c7f8SJohn Dyson ((p->queue - p->pc) == PQ_CACHE)) { 524bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 525aef922f5SJohn Dyson continue; 526f6b04d2bSDavid Greenman } 527f6b04d2bSDavid Greenman 528bd7e5f99SJohn Dyson vm_page_test_dirty(p); 529bd7e5f99SJohn Dyson if ((p->dirty & p->valid) == 0) { 530bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 531bd7e5f99SJohn Dyson continue; 532bd7e5f99SJohn Dyson } 533ec4f9fb0SDavid Greenman 534b18bfc3dSJohn Dyson s = splvm(); 535bd7e5f99SJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 536aef922f5SJohn Dyson p->flags |= PG_WANTED|PG_REFERENCED; 537aef922f5SJohn Dyson tsleep(p, PVM, "vpcwai", 0); 538f6b04d2bSDavid Greenman splx(s); 539bd7e5f99SJohn Dyson goto rescan; 540f6b04d2bSDavid Greenman } 541f6b04d2bSDavid Greenman splx(s); 542f6b04d2bSDavid Greenman 543f35329acSJohn Dyson s = splvm(); 544bd7e5f99SJohn Dyson maxf = 0; 545bd7e5f99SJohn Dyson for(i=1;i<vm_pageout_page_count;i++) { 546bd7e5f99SJohn Dyson if (tp = vm_page_lookup(object, pi + i)) { 547bd7e5f99SJohn Dyson if ((tp->flags & PG_BUSY) || 548bd7e5f99SJohn Dyson (tp->flags & PG_CLEANCHK) == 0) 549bd7e5f99SJohn Dyson break; 5505070c7f8SJohn Dyson if((tp->queue - tp->pc) == PQ_CACHE) { 5513077a9c2SJohn Dyson tp->flags &= ~PG_CLEANCHK; 5523077a9c2SJohn Dyson break; 5533077a9c2SJohn Dyson } 554bd7e5f99SJohn Dyson vm_page_test_dirty(tp); 555bd7e5f99SJohn Dyson if ((tp->dirty & tp->valid) == 0) { 556bd7e5f99SJohn Dyson tp->flags &= ~PG_CLEANCHK; 557bd7e5f99SJohn Dyson break; 558bd7e5f99SJohn Dyson } 559bd7e5f99SJohn Dyson maf[ i - 1 ] = tp; 560bd7e5f99SJohn Dyson maxf++; 561bd7e5f99SJohn Dyson continue; 562bd7e5f99SJohn Dyson } 563bd7e5f99SJohn Dyson break; 564bd7e5f99SJohn Dyson } 565aef922f5SJohn Dyson 566bd7e5f99SJohn Dyson maxb = 0; 567bd7e5f99SJohn Dyson chkb = vm_pageout_page_count - maxf; 568bd7e5f99SJohn Dyson if (chkb) { 569bd7e5f99SJohn Dyson for(i = 1; i < chkb;i++) { 570bd7e5f99SJohn Dyson if (tp = vm_page_lookup(object, pi - i)) { 571bd7e5f99SJohn Dyson if ((tp->flags & PG_BUSY) || 572bd7e5f99SJohn Dyson (tp->flags & PG_CLEANCHK) == 0) 573bd7e5f99SJohn Dyson break; 5745070c7f8SJohn Dyson if((tp->queue - tp->pc) == PQ_CACHE) { 5753077a9c2SJohn Dyson tp->flags &= ~PG_CLEANCHK; 5763077a9c2SJohn Dyson break; 5773077a9c2SJohn Dyson } 578bd7e5f99SJohn Dyson vm_page_test_dirty(tp); 579bd7e5f99SJohn Dyson if ((tp->dirty & tp->valid) == 0) { 580bd7e5f99SJohn Dyson tp->flags &= ~PG_CLEANCHK; 581bd7e5f99SJohn Dyson break; 582bd7e5f99SJohn Dyson } 583bd7e5f99SJohn Dyson mab[ i - 1 ] = tp; 584bd7e5f99SJohn Dyson maxb++; 585bd7e5f99SJohn Dyson continue; 586bd7e5f99SJohn Dyson } 587bd7e5f99SJohn Dyson break; 588bd7e5f99SJohn Dyson } 589bd7e5f99SJohn Dyson } 590bd7e5f99SJohn Dyson 591bd7e5f99SJohn Dyson for(i=0;i<maxb;i++) { 592bd7e5f99SJohn Dyson int index = (maxb - i) - 1; 593bd7e5f99SJohn Dyson ma[index] = mab[i]; 594bd7e5f99SJohn Dyson ma[index]->flags |= PG_BUSY; 595bd7e5f99SJohn Dyson ma[index]->flags &= ~PG_CLEANCHK; 596bd7e5f99SJohn Dyson vm_page_protect(ma[index], VM_PROT_READ); 597bd7e5f99SJohn Dyson } 598bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_READ); 599aef922f5SJohn Dyson p->flags |= PG_BUSY; 600bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 601bd7e5f99SJohn Dyson ma[maxb] = p; 602bd7e5f99SJohn Dyson for(i=0;i<maxf;i++) { 603bd7e5f99SJohn Dyson int index = (maxb + i) + 1; 604bd7e5f99SJohn Dyson ma[index] = maf[i]; 605bd7e5f99SJohn Dyson ma[index]->flags |= PG_BUSY; 606bd7e5f99SJohn Dyson ma[index]->flags &= ~PG_CLEANCHK; 607bd7e5f99SJohn Dyson vm_page_protect(ma[index], VM_PROT_READ); 608f6b04d2bSDavid Greenman } 609bd7e5f99SJohn Dyson runlen = maxb + maxf + 1; 610f35329acSJohn Dyson splx(s); 611bd7e5f99SJohn Dyson vm_pageout_flush(ma, runlen, 0); 612bd7e5f99SJohn Dyson goto rescan; 613f6b04d2bSDavid Greenman } 614aef922f5SJohn Dyson 615aef922f5SJohn Dyson VOP_FSYNC(vp, NULL, syncio, curproc); 616aef922f5SJohn Dyson 61724a1cce3SDavid Greenman if (lockflag) 618996c772fSJohn Dyson VOP_UNLOCK(vp, 0, pproc); 619aef922f5SJohn Dyson object->flags &= ~OBJ_CLEANING; 620f5cf85d4SDavid Greenman return; 62126f9a767SRodney W. Grimes } 622df8bae1dSRodney W. Grimes 623f708ef1bSPoul-Henning Kamp #ifdef not_used 624f708ef1bSPoul-Henning Kamp /* XXX I cannot tell if this should be an exported symbol */ 625df8bae1dSRodney W. Grimes /* 626df8bae1dSRodney W. Grimes * vm_object_deactivate_pages 627df8bae1dSRodney W. Grimes * 628df8bae1dSRodney W. Grimes * Deactivate all pages in the specified object. (Keep its pages 629df8bae1dSRodney W. Grimes * in memory even though it is no longer referenced.) 630df8bae1dSRodney W. Grimes * 631df8bae1dSRodney W. Grimes * The object must be locked. 632df8bae1dSRodney W. Grimes */ 633f708ef1bSPoul-Henning Kamp static void 634df8bae1dSRodney W. Grimes vm_object_deactivate_pages(object) 635df8bae1dSRodney W. Grimes register vm_object_t object; 636df8bae1dSRodney W. Grimes { 637df8bae1dSRodney W. Grimes register vm_page_t p, next; 638df8bae1dSRodney W. Grimes 639b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 640b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 641df8bae1dSRodney W. Grimes vm_page_deactivate(p); 642df8bae1dSRodney W. Grimes } 643df8bae1dSRodney W. Grimes } 644f708ef1bSPoul-Henning Kamp #endif 645df8bae1dSRodney W. Grimes 646df8bae1dSRodney W. Grimes /* 647df8bae1dSRodney W. Grimes * Trim the object cache to size. 648df8bae1dSRodney W. Grimes */ 649f708ef1bSPoul-Henning Kamp static void 650df8bae1dSRodney W. Grimes vm_object_cache_trim() 651df8bae1dSRodney W. Grimes { 652df8bae1dSRodney W. Grimes register vm_object_t object; 653df8bae1dSRodney W. Grimes 6540d94caffSDavid Greenman while (vm_object_cached > vm_object_cache_max) { 655b18bfc3dSJohn Dyson object = TAILQ_FIRST(&vm_object_cached_list); 656df8bae1dSRodney W. Grimes 65724a1cce3SDavid Greenman vm_object_reference(object); 658df8bae1dSRodney W. Grimes pager_cache(object, FALSE); 659df8bae1dSRodney W. Grimes } 660df8bae1dSRodney W. Grimes } 661df8bae1dSRodney W. Grimes 66226f9a767SRodney W. Grimes 663df8bae1dSRodney W. Grimes /* 664df8bae1dSRodney W. Grimes * vm_object_pmap_copy: 665df8bae1dSRodney W. Grimes * 666df8bae1dSRodney W. Grimes * Makes all physical pages in the specified 667df8bae1dSRodney W. Grimes * object range copy-on-write. No writeable 668df8bae1dSRodney W. Grimes * references to these pages should remain. 669df8bae1dSRodney W. Grimes * 670df8bae1dSRodney W. Grimes * The object must *not* be locked. 671df8bae1dSRodney W. Grimes */ 6720d94caffSDavid Greenman void 6730d94caffSDavid Greenman vm_object_pmap_copy(object, start, end) 674df8bae1dSRodney W. Grimes register vm_object_t object; 675a316d390SJohn Dyson register vm_pindex_t start; 676a316d390SJohn Dyson register vm_pindex_t end; 677df8bae1dSRodney W. Grimes { 678df8bae1dSRodney W. Grimes register vm_page_t p; 679df8bae1dSRodney W. Grimes 680aef922f5SJohn Dyson if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) 681df8bae1dSRodney W. Grimes return; 682df8bae1dSRodney W. Grimes 683b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 684b5b40fa6SJohn Dyson p != NULL; 685b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 686f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_READ); 687df8bae1dSRodney W. Grimes } 688aef922f5SJohn Dyson 689aef922f5SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 690df8bae1dSRodney W. Grimes } 691df8bae1dSRodney W. Grimes 692df8bae1dSRodney W. Grimes /* 6931efb74fbSJohn Dyson * Same as vm_object_pmap_copy_1, except range checking really 6941efb74fbSJohn Dyson * works, and is meant for small sections of an object. 6951efb74fbSJohn Dyson */ 6961efb74fbSJohn Dyson void 6971efb74fbSJohn Dyson vm_object_pmap_copy_1(object, start, end) 6981efb74fbSJohn Dyson register vm_object_t object; 6991efb74fbSJohn Dyson register vm_pindex_t start; 7001efb74fbSJohn Dyson register vm_pindex_t end; 7011efb74fbSJohn Dyson { 7021efb74fbSJohn Dyson vm_pindex_t idx; 7031efb74fbSJohn Dyson register vm_page_t p; 7041efb74fbSJohn Dyson 7051efb74fbSJohn Dyson if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) 7061efb74fbSJohn Dyson return; 7071efb74fbSJohn Dyson 7081efb74fbSJohn Dyson for (idx = start; idx < end; idx++) { 7091efb74fbSJohn Dyson p = vm_page_lookup(object, idx); 7101efb74fbSJohn Dyson if (p == NULL) 7111efb74fbSJohn Dyson continue; 7121efb74fbSJohn Dyson vm_page_protect(p, VM_PROT_READ); 7131efb74fbSJohn Dyson } 7141efb74fbSJohn Dyson } 7151efb74fbSJohn Dyson 7161efb74fbSJohn Dyson /* 717df8bae1dSRodney W. Grimes * vm_object_pmap_remove: 718df8bae1dSRodney W. Grimes * 719df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 720df8bae1dSRodney W. Grimes * object range from all physical maps. 721df8bae1dSRodney W. Grimes * 722df8bae1dSRodney W. Grimes * The object must *not* be locked. 723df8bae1dSRodney W. Grimes */ 72426f9a767SRodney W. Grimes void 72526f9a767SRodney W. Grimes vm_object_pmap_remove(object, start, end) 726df8bae1dSRodney W. Grimes register vm_object_t object; 727a316d390SJohn Dyson register vm_pindex_t start; 728a316d390SJohn Dyson register vm_pindex_t end; 729df8bae1dSRodney W. Grimes { 730df8bae1dSRodney W. Grimes register vm_page_t p; 731df8bae1dSRodney W. Grimes if (object == NULL) 732df8bae1dSRodney W. Grimes return; 733b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 734b5b40fa6SJohn Dyson p != NULL; 735b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 736bd7e5f99SJohn Dyson if (p->pindex >= start && p->pindex < end) 737f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 73826f9a767SRodney W. Grimes } 7396e20a165SJohn Dyson if ((start == 0) && (object->size == end)) 7406e20a165SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 74126f9a767SRodney W. Grimes } 742df8bae1dSRodney W. Grimes 743df8bae1dSRodney W. Grimes /* 744867a482dSJohn Dyson * vm_object_madvise: 745867a482dSJohn Dyson * 746867a482dSJohn Dyson * Implements the madvise function at the object/page level. 747867a482dSJohn Dyson */ 748867a482dSJohn Dyson void 749867a482dSJohn Dyson vm_object_madvise(object, pindex, count, advise) 750867a482dSJohn Dyson vm_object_t object; 751867a482dSJohn Dyson vm_pindex_t pindex; 752867a482dSJohn Dyson int count; 753867a482dSJohn Dyson int advise; 754867a482dSJohn Dyson { 7556e20a165SJohn Dyson int s; 7566e20a165SJohn Dyson vm_pindex_t end, tpindex; 7576e20a165SJohn Dyson vm_object_t tobject; 758867a482dSJohn Dyson vm_page_t m; 759867a482dSJohn Dyson 760867a482dSJohn Dyson if (object == NULL) 761867a482dSJohn Dyson return; 762867a482dSJohn Dyson 763867a482dSJohn Dyson end = pindex + count; 764867a482dSJohn Dyson 765867a482dSJohn Dyson for (; pindex < end; pindex += 1) { 7666e20a165SJohn Dyson 7676e20a165SJohn Dyson relookup: 7686e20a165SJohn Dyson tobject = object; 7696e20a165SJohn Dyson tpindex = pindex; 7706e20a165SJohn Dyson shadowlookup: 7716e20a165SJohn Dyson m = vm_page_lookup(tobject, tpindex); 7726e20a165SJohn Dyson if (m == NULL) { 7736e20a165SJohn Dyson if (tobject->type != OBJT_DEFAULT) { 7746e20a165SJohn Dyson continue; 7756e20a165SJohn Dyson } 7766e20a165SJohn Dyson 7776e20a165SJohn Dyson tobject = tobject->backing_object; 7786e20a165SJohn Dyson if ((tobject == NULL) || (tobject->ref_count != 1)) { 7796e20a165SJohn Dyson continue; 7806e20a165SJohn Dyson } 7816e20a165SJohn Dyson tpindex += OFF_TO_IDX(tobject->backing_object_offset); 7826e20a165SJohn Dyson goto shadowlookup; 7836e20a165SJohn Dyson } 784867a482dSJohn Dyson 785867a482dSJohn Dyson /* 786867a482dSJohn Dyson * If the page is busy or not in a normal active state, 787867a482dSJohn Dyson * we skip it. Things can break if we mess with pages 788867a482dSJohn Dyson * in any of the below states. 789867a482dSJohn Dyson */ 7906e20a165SJohn Dyson if (m->hold_count || m->wire_count || 7916e20a165SJohn Dyson m->valid != VM_PAGE_BITS_ALL) { 792867a482dSJohn Dyson continue; 7936e20a165SJohn Dyson } 7946e20a165SJohn Dyson 7956e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7966e20a165SJohn Dyson s = splvm(); 7976e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7986e20a165SJohn Dyson m->flags |= PG_WANTED; 7996e20a165SJohn Dyson tsleep(m, PVM, "madvpw", 0); 8006e20a165SJohn Dyson } 8016e20a165SJohn Dyson splx(s); 8026e20a165SJohn Dyson goto relookup; 8036e20a165SJohn Dyson } 804867a482dSJohn Dyson 805867a482dSJohn Dyson if (advise == MADV_WILLNEED) { 806867a482dSJohn Dyson if (m->queue != PQ_ACTIVE) 807867a482dSJohn Dyson vm_page_activate(m); 8086e20a165SJohn Dyson } else if (advise == MADV_DONTNEED) { 809867a482dSJohn Dyson vm_page_deactivate(m); 8100a47b48bSJohn Dyson } else if (advise == MADV_FREE) { 8116e20a165SJohn Dyson pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 8126e20a165SJohn Dyson m->dirty = 0; 8130a47b48bSJohn Dyson /* 8146e20a165SJohn Dyson * Force a demand zero if attempt to read from swap. 8156e20a165SJohn Dyson * We currently don't handle vnode files correctly, 8166e20a165SJohn Dyson * and will reread stale contents unnecessarily. 8170a47b48bSJohn Dyson */ 8180a47b48bSJohn Dyson if (object->type == OBJT_SWAP) 8196e20a165SJohn Dyson swap_pager_dmzspace(tobject, m->pindex, 1); 820867a482dSJohn Dyson } 821867a482dSJohn Dyson } 822867a482dSJohn Dyson } 823867a482dSJohn Dyson 824867a482dSJohn Dyson /* 825df8bae1dSRodney W. Grimes * vm_object_shadow: 826df8bae1dSRodney W. Grimes * 827df8bae1dSRodney W. Grimes * Create a new object which is backed by the 828df8bae1dSRodney W. Grimes * specified existing object range. The source 829df8bae1dSRodney W. Grimes * object reference is deallocated. 830df8bae1dSRodney W. Grimes * 831df8bae1dSRodney W. Grimes * The new object and offset into that object 832df8bae1dSRodney W. Grimes * are returned in the source parameters. 833df8bae1dSRodney W. Grimes */ 834df8bae1dSRodney W. Grimes 83526f9a767SRodney W. Grimes void 83626f9a767SRodney W. Grimes vm_object_shadow(object, offset, length) 837df8bae1dSRodney W. Grimes vm_object_t *object; /* IN/OUT */ 838a316d390SJohn Dyson vm_ooffset_t *offset; /* IN/OUT */ 839df8bae1dSRodney W. Grimes vm_size_t length; 840df8bae1dSRodney W. Grimes { 841df8bae1dSRodney W. Grimes register vm_object_t source; 842df8bae1dSRodney W. Grimes register vm_object_t result; 843df8bae1dSRodney W. Grimes 844df8bae1dSRodney W. Grimes source = *object; 845df8bae1dSRodney W. Grimes 846df8bae1dSRodney W. Grimes /* 847df8bae1dSRodney W. Grimes * Allocate a new object with the given length 848df8bae1dSRodney W. Grimes */ 849df8bae1dSRodney W. Grimes 85024a1cce3SDavid Greenman if ((result = vm_object_allocate(OBJT_DEFAULT, length)) == NULL) 851df8bae1dSRodney W. Grimes panic("vm_object_shadow: no object for shadowing"); 852df8bae1dSRodney W. Grimes 853df8bae1dSRodney W. Grimes /* 8540d94caffSDavid Greenman * The new object shadows the source object, adding a reference to it. 8550d94caffSDavid Greenman * Our caller changes his reference to point to the new object, 8560d94caffSDavid Greenman * removing a reference to the source object. Net result: no change 8570d94caffSDavid Greenman * of reference count. 858df8bae1dSRodney W. Grimes */ 85924a1cce3SDavid Greenman result->backing_object = source; 860de5f6a77SJohn Dyson if (source) { 861de5f6a77SJohn Dyson TAILQ_INSERT_TAIL(&source->shadow_head, result, shadow_list); 862de5f6a77SJohn Dyson ++source->shadow_count; 863de5f6a77SJohn Dyson } 864df8bae1dSRodney W. Grimes 865df8bae1dSRodney W. Grimes /* 8660d94caffSDavid Greenman * Store the offset into the source object, and fix up the offset into 8670d94caffSDavid Greenman * the new object. 868df8bae1dSRodney W. Grimes */ 869df8bae1dSRodney W. Grimes 87024a1cce3SDavid Greenman result->backing_object_offset = *offset; 871df8bae1dSRodney W. Grimes 872df8bae1dSRodney W. Grimes /* 873df8bae1dSRodney W. Grimes * Return the new things 874df8bae1dSRodney W. Grimes */ 875df8bae1dSRodney W. Grimes 876df8bae1dSRodney W. Grimes *offset = 0; 877df8bae1dSRodney W. Grimes *object = result; 878df8bae1dSRodney W. Grimes } 879df8bae1dSRodney W. Grimes 880df8bae1dSRodney W. Grimes 881df8bae1dSRodney W. Grimes /* 8822fe6e4d7SDavid Greenman * this version of collapse allows the operation to occur earlier and 8832fe6e4d7SDavid Greenman * when paging_in_progress is true for an object... This is not a complete 8842fe6e4d7SDavid Greenman * operation, but should plug 99.9% of the rest of the leaks. 8852fe6e4d7SDavid Greenman */ 8862fe6e4d7SDavid Greenman static void 8872fe6e4d7SDavid Greenman vm_object_qcollapse(object) 8882fe6e4d7SDavid Greenman register vm_object_t object; 8892fe6e4d7SDavid Greenman { 8902fe6e4d7SDavid Greenman register vm_object_t backing_object; 891a316d390SJohn Dyson register vm_pindex_t backing_offset_index, paging_offset_index; 892a316d390SJohn Dyson vm_pindex_t backing_object_paging_offset_index; 893a316d390SJohn Dyson vm_pindex_t new_pindex; 8942fe6e4d7SDavid Greenman register vm_page_t p, pp; 8952fe6e4d7SDavid Greenman register vm_size_t size; 8962fe6e4d7SDavid Greenman 89724a1cce3SDavid Greenman backing_object = object->backing_object; 8982fe6e4d7SDavid Greenman if (backing_object->ref_count != 1) 8992fe6e4d7SDavid Greenman return; 9002fe6e4d7SDavid Greenman 901010cf3b9SDavid Greenman backing_object->ref_count += 2; 902010cf3b9SDavid Greenman 903a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(object->backing_object_offset); 904a316d390SJohn Dyson backing_object_paging_offset_index = OFF_TO_IDX(backing_object->paging_offset); 905a316d390SJohn Dyson paging_offset_index = OFF_TO_IDX(object->paging_offset); 9062fe6e4d7SDavid Greenman size = object->size; 907b18bfc3dSJohn Dyson p = TAILQ_FIRST(&backing_object->memq); 9082fe6e4d7SDavid Greenman while (p) { 9092fe6e4d7SDavid Greenman vm_page_t next; 9100d94caffSDavid Greenman 911b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 912bd7e5f99SJohn Dyson if ((p->flags & (PG_BUSY | PG_FICTITIOUS)) || 9135070c7f8SJohn Dyson ((p->queue - p->pc) == PQ_CACHE) || 9145070c7f8SJohn Dyson !p->valid || p->hold_count || p->wire_count || p->busy) { 9152fe6e4d7SDavid Greenman p = next; 9162fe6e4d7SDavid Greenman continue; 9172fe6e4d7SDavid Greenman } 918a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 919a316d390SJohn Dyson if (p->pindex < backing_offset_index || 920a316d390SJohn Dyson new_pindex >= size) { 92124a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 92224a1cce3SDavid Greenman swap_pager_freespace(backing_object, 923a316d390SJohn Dyson backing_object_paging_offset_index+p->pindex, 924a316d390SJohn Dyson 1); 925b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9262fe6e4d7SDavid Greenman vm_page_free(p); 9272fe6e4d7SDavid Greenman } else { 928a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 92924a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 930a316d390SJohn Dyson paging_offset_index + new_pindex, NULL, NULL))) { 93124a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 93224a1cce3SDavid Greenman swap_pager_freespace(backing_object, 933a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 934b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9352fe6e4d7SDavid Greenman vm_page_free(p); 9362fe6e4d7SDavid Greenman } else { 93724a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 93824a1cce3SDavid Greenman swap_pager_freespace(backing_object, 939a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 940a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 9416e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9429b4814bbSDavid Greenman p->dirty = VM_PAGE_BITS_ALL; 9432fe6e4d7SDavid Greenman } 9442fe6e4d7SDavid Greenman } 9452fe6e4d7SDavid Greenman p = next; 9462fe6e4d7SDavid Greenman } 947010cf3b9SDavid Greenman backing_object->ref_count -= 2; 9482fe6e4d7SDavid Greenman } 9492fe6e4d7SDavid Greenman 950df8bae1dSRodney W. Grimes /* 951df8bae1dSRodney W. Grimes * vm_object_collapse: 952df8bae1dSRodney W. Grimes * 953df8bae1dSRodney W. Grimes * Collapse an object with the object backing it. 954df8bae1dSRodney W. Grimes * Pages in the backing object are moved into the 955df8bae1dSRodney W. Grimes * parent, and the backing object is deallocated. 956df8bae1dSRodney W. Grimes */ 95726f9a767SRodney W. Grimes void 95826f9a767SRodney W. Grimes vm_object_collapse(object) 95924a1cce3SDavid Greenman vm_object_t object; 960df8bae1dSRodney W. Grimes 961df8bae1dSRodney W. Grimes { 96224a1cce3SDavid Greenman vm_object_t backing_object; 963a316d390SJohn Dyson vm_ooffset_t backing_offset; 96424a1cce3SDavid Greenman vm_size_t size; 965a316d390SJohn Dyson vm_pindex_t new_pindex, backing_offset_index; 96624a1cce3SDavid Greenman vm_page_t p, pp; 967df8bae1dSRodney W. Grimes 968df8bae1dSRodney W. Grimes while (TRUE) { 969df8bae1dSRodney W. Grimes /* 970df8bae1dSRodney W. Grimes * Verify that the conditions are right for collapse: 971df8bae1dSRodney W. Grimes * 9720d94caffSDavid Greenman * The object exists and no pages in it are currently being paged 9730d94caffSDavid Greenman * out. 974df8bae1dSRodney W. Grimes */ 9752fe6e4d7SDavid Greenman if (object == NULL) 976df8bae1dSRodney W. Grimes return; 977df8bae1dSRodney W. Grimes 978b9921222SDavid Greenman /* 979b9921222SDavid Greenman * Make sure there is a backing object. 980b9921222SDavid Greenman */ 98124a1cce3SDavid Greenman if ((backing_object = object->backing_object) == NULL) 982df8bae1dSRodney W. Grimes return; 983df8bae1dSRodney W. Grimes 984f919ebdeSDavid Greenman /* 985f919ebdeSDavid Greenman * we check the backing object first, because it is most likely 98624a1cce3SDavid Greenman * not collapsable. 987f919ebdeSDavid Greenman */ 98824a1cce3SDavid Greenman if (backing_object->handle != NULL || 98924a1cce3SDavid Greenman (backing_object->type != OBJT_DEFAULT && 99024a1cce3SDavid Greenman backing_object->type != OBJT_SWAP) || 991f919ebdeSDavid Greenman (backing_object->flags & OBJ_DEAD) || 99224a1cce3SDavid Greenman object->handle != NULL || 99324a1cce3SDavid Greenman (object->type != OBJT_DEFAULT && 99424a1cce3SDavid Greenman object->type != OBJT_SWAP) || 99524a1cce3SDavid Greenman (object->flags & OBJ_DEAD)) { 9969b4814bbSDavid Greenman return; 99724a1cce3SDavid Greenman } 9989b4814bbSDavid Greenman 999f919ebdeSDavid Greenman if (object->paging_in_progress != 0 || 1000f919ebdeSDavid Greenman backing_object->paging_in_progress != 0) { 1001b9921222SDavid Greenman vm_object_qcollapse(object); 1002df8bae1dSRodney W. Grimes return; 1003df8bae1dSRodney W. Grimes } 1004f919ebdeSDavid Greenman 100526f9a767SRodney W. Grimes /* 10060d94caffSDavid Greenman * We know that we can either collapse the backing object (if 10070d94caffSDavid Greenman * the parent is the only reference to it) or (perhaps) remove 10080d94caffSDavid Greenman * the parent's reference to it. 1009df8bae1dSRodney W. Grimes */ 1010df8bae1dSRodney W. Grimes 101124a1cce3SDavid Greenman backing_offset = object->backing_object_offset; 1012a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(backing_offset); 1013df8bae1dSRodney W. Grimes size = object->size; 1014df8bae1dSRodney W. Grimes 1015df8bae1dSRodney W. Grimes /* 10160d94caffSDavid Greenman * If there is exactly one reference to the backing object, we 10170d94caffSDavid Greenman * can collapse it into the parent. 1018df8bae1dSRodney W. Grimes */ 1019df8bae1dSRodney W. Grimes 1020df8bae1dSRodney W. Grimes if (backing_object->ref_count == 1) { 1021df8bae1dSRodney W. Grimes 1022a1f6d91cSDavid Greenman backing_object->flags |= OBJ_DEAD; 1023df8bae1dSRodney W. Grimes /* 1024df8bae1dSRodney W. Grimes * We can collapse the backing object. 1025df8bae1dSRodney W. Grimes * 10260d94caffSDavid Greenman * Move all in-memory pages from backing_object to the 10270d94caffSDavid Greenman * parent. Pages that have been paged out will be 10280d94caffSDavid Greenman * overwritten by any of the parent's pages that 10290d94caffSDavid Greenman * shadow them. 1030df8bae1dSRodney W. Grimes */ 1031df8bae1dSRodney W. Grimes 1032b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&backing_object->memq)) != 0) { 103326f9a767SRodney W. Grimes 1034a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 1035df8bae1dSRodney W. Grimes 1036df8bae1dSRodney W. Grimes /* 10370d94caffSDavid Greenman * If the parent has a page here, or if this 10380d94caffSDavid Greenman * page falls outside the parent, dispose of 10390d94caffSDavid Greenman * it. 1040df8bae1dSRodney W. Grimes * 1041df8bae1dSRodney W. Grimes * Otherwise, move it as planned. 1042df8bae1dSRodney W. Grimes */ 1043df8bae1dSRodney W. Grimes 1044a316d390SJohn Dyson if (p->pindex < backing_offset_index || 1045a316d390SJohn Dyson new_pindex >= size) { 1046f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 10470d94caffSDavid Greenman PAGE_WAKEUP(p); 1048df8bae1dSRodney W. Grimes vm_page_free(p); 1049df8bae1dSRodney W. Grimes } else { 1050a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 105124a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 1052a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL))) { 1053f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 10540d94caffSDavid Greenman PAGE_WAKEUP(p); 1055df8bae1dSRodney W. Grimes vm_page_free(p); 105626f9a767SRodney W. Grimes } else { 10576e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1058a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 10596e20a165SJohn Dyson p->dirty = VM_PAGE_BITS_ALL; 1060df8bae1dSRodney W. Grimes } 1061df8bae1dSRodney W. Grimes } 1062df8bae1dSRodney W. Grimes } 1063df8bae1dSRodney W. Grimes 1064df8bae1dSRodney W. Grimes /* 1065df8bae1dSRodney W. Grimes * Move the pager from backing_object to object. 1066df8bae1dSRodney W. Grimes */ 1067df8bae1dSRodney W. Grimes 106824a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) { 106926f9a767SRodney W. Grimes backing_object->paging_in_progress++; 107024a1cce3SDavid Greenman if (object->type == OBJT_SWAP) { 107126f9a767SRodney W. Grimes object->paging_in_progress++; 107226f9a767SRodney W. Grimes /* 107326f9a767SRodney W. Grimes * copy shadow object pages into ours 10740d94caffSDavid Greenman * and destroy unneeded pages in 10750d94caffSDavid Greenman * shadow object. 107626f9a767SRodney W. Grimes */ 107726f9a767SRodney W. Grimes swap_pager_copy( 1078a316d390SJohn Dyson backing_object, 1079a316d390SJohn Dyson OFF_TO_IDX(backing_object->paging_offset), 1080a316d390SJohn Dyson object, 1081a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset), 1082a316d390SJohn Dyson OFF_TO_IDX(object->backing_object_offset)); 1083f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 108426f9a767SRodney W. Grimes } else { 108526f9a767SRodney W. Grimes object->paging_in_progress++; 108626f9a767SRodney W. Grimes /* 108724a1cce3SDavid Greenman * move the shadow backing_object's pager data to 108824a1cce3SDavid Greenman * "object" and convert "object" type to OBJT_SWAP. 108926f9a767SRodney W. Grimes */ 109024a1cce3SDavid Greenman object->type = OBJT_SWAP; 10912a4895f4SDavid Greenman object->un_pager.swp.swp_nblocks = 10922a4895f4SDavid Greenman backing_object->un_pager.swp.swp_nblocks; 10932a4895f4SDavid Greenman object->un_pager.swp.swp_allocsize = 10942a4895f4SDavid Greenman backing_object->un_pager.swp.swp_allocsize; 10952a4895f4SDavid Greenman object->un_pager.swp.swp_blocks = 10962a4895f4SDavid Greenman backing_object->un_pager.swp.swp_blocks; 10972a4895f4SDavid Greenman object->un_pager.swp.swp_poip = /* XXX */ 10982a4895f4SDavid Greenman backing_object->un_pager.swp.swp_poip; 109926f9a767SRodney W. Grimes object->paging_offset = backing_object->paging_offset + backing_offset; 110024a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&swap_pager_un_object_list, object, pager_object_list); 110124a1cce3SDavid Greenman 110224a1cce3SDavid Greenman /* 110324a1cce3SDavid Greenman * Convert backing object from OBJT_SWAP to 110424a1cce3SDavid Greenman * OBJT_DEFAULT. XXX - only the TAILQ_REMOVE is 110524a1cce3SDavid Greenman * actually necessary. 110624a1cce3SDavid Greenman */ 110724a1cce3SDavid Greenman backing_object->type = OBJT_DEFAULT; 110824a1cce3SDavid Greenman TAILQ_REMOVE(&swap_pager_un_object_list, backing_object, pager_object_list); 110926f9a767SRodney W. Grimes /* 111026f9a767SRodney W. Grimes * free unnecessary blocks 111126f9a767SRodney W. Grimes */ 1112a316d390SJohn Dyson swap_pager_freespace(object, 0, 1113a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset)); 1114f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1115c0503609SDavid Greenman } 1116c0503609SDavid Greenman 1117f919ebdeSDavid Greenman vm_object_pip_wakeup(backing_object); 1118c0503609SDavid Greenman } 1119df8bae1dSRodney W. Grimes /* 1120df8bae1dSRodney W. Grimes * Object now shadows whatever backing_object did. 112124a1cce3SDavid Greenman * Note that the reference to backing_object->backing_object 1122df8bae1dSRodney W. Grimes * moves from within backing_object to within object. 1123df8bae1dSRodney W. Grimes */ 1124df8bae1dSRodney W. Grimes 112524a1cce3SDavid Greenman TAILQ_REMOVE(&object->backing_object->shadow_head, object, 112624a1cce3SDavid Greenman shadow_list); 1127de5f6a77SJohn Dyson --object->backing_object->shadow_count; 1128de5f6a77SJohn Dyson if (backing_object->backing_object) { 112924a1cce3SDavid Greenman TAILQ_REMOVE(&backing_object->backing_object->shadow_head, 113024a1cce3SDavid Greenman backing_object, shadow_list); 1131de5f6a77SJohn Dyson --backing_object->backing_object->shadow_count; 1132de5f6a77SJohn Dyson } 113324a1cce3SDavid Greenman object->backing_object = backing_object->backing_object; 1134de5f6a77SJohn Dyson if (object->backing_object) { 113524a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&object->backing_object->shadow_head, 113624a1cce3SDavid Greenman object, shadow_list); 1137de5f6a77SJohn Dyson ++object->backing_object->shadow_count; 1138de5f6a77SJohn Dyson } 11392fe6e4d7SDavid Greenman 114024a1cce3SDavid Greenman object->backing_object_offset += backing_object->backing_object_offset; 1141df8bae1dSRodney W. Grimes /* 1142df8bae1dSRodney W. Grimes * Discard backing_object. 1143df8bae1dSRodney W. Grimes * 11440d94caffSDavid Greenman * Since the backing object has no pages, no pager left, 11450d94caffSDavid Greenman * and no object references within it, all that is 11460d94caffSDavid Greenman * necessary is to dispose of it. 1147df8bae1dSRodney W. Grimes */ 1148df8bae1dSRodney W. Grimes 1149df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, backing_object, 1150df8bae1dSRodney W. Grimes object_list); 1151df8bae1dSRodney W. Grimes vm_object_count--; 1152df8bae1dSRodney W. Grimes 115399448ed1SJohn Dyson zfree(obj_zone, backing_object); 1154df8bae1dSRodney W. Grimes 1155df8bae1dSRodney W. Grimes object_collapses++; 11560d94caffSDavid Greenman } else { 1157df8bae1dSRodney W. Grimes /* 1158df8bae1dSRodney W. Grimes * If all of the pages in the backing object are 11590d94caffSDavid Greenman * shadowed by the parent object, the parent object no 11600d94caffSDavid Greenman * longer has to shadow the backing object; it can 11610d94caffSDavid Greenman * shadow the next one in the chain. 1162df8bae1dSRodney W. Grimes * 11630d94caffSDavid Greenman * The backing object must not be paged out - we'd have 11640d94caffSDavid Greenman * to check all of the paged-out pages, as well. 1165df8bae1dSRodney W. Grimes */ 1166df8bae1dSRodney W. Grimes 116724a1cce3SDavid Greenman if (backing_object->type != OBJT_DEFAULT) { 1168df8bae1dSRodney W. Grimes return; 1169df8bae1dSRodney W. Grimes } 1170df8bae1dSRodney W. Grimes /* 11710d94caffSDavid Greenman * Should have a check for a 'small' number of pages 11720d94caffSDavid Greenman * here. 1173df8bae1dSRodney W. Grimes */ 1174df8bae1dSRodney W. Grimes 1175b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&backing_object->memq); p; p = TAILQ_NEXT(p, listq)) { 1176a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 1177df8bae1dSRodney W. Grimes 1178df8bae1dSRodney W. Grimes /* 11790d94caffSDavid Greenman * If the parent has a page here, or if this 11800d94caffSDavid Greenman * page falls outside the parent, keep going. 1181df8bae1dSRodney W. Grimes * 11820d94caffSDavid Greenman * Otherwise, the backing_object must be left in 11830d94caffSDavid Greenman * the chain. 1184df8bae1dSRodney W. Grimes */ 1185df8bae1dSRodney W. Grimes 1186a316d390SJohn Dyson if (p->pindex >= backing_offset_index && 1187a316d390SJohn Dyson new_pindex <= size) { 118824a1cce3SDavid Greenman 1189a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 119024a1cce3SDavid Greenman 119124a1cce3SDavid Greenman if ((pp == NULL || pp->valid == 0) && 1192a316d390SJohn Dyson !vm_pager_has_page(object, OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL)) { 1193df8bae1dSRodney W. Grimes /* 11940d94caffSDavid Greenman * Page still needed. Can't go any 11950d94caffSDavid Greenman * further. 1196df8bae1dSRodney W. Grimes */ 1197df8bae1dSRodney W. Grimes return; 1198df8bae1dSRodney W. Grimes } 1199df8bae1dSRodney W. Grimes } 120024a1cce3SDavid Greenman } 1201df8bae1dSRodney W. Grimes 1202df8bae1dSRodney W. Grimes /* 12030d94caffSDavid Greenman * Make the parent shadow the next object in the 12040d94caffSDavid Greenman * chain. Deallocating backing_object will not remove 12050d94caffSDavid Greenman * it, since its reference count is at least 2. 1206df8bae1dSRodney W. Grimes */ 1207df8bae1dSRodney W. Grimes 120824a1cce3SDavid Greenman TAILQ_REMOVE(&object->backing_object->shadow_head, 120924a1cce3SDavid Greenman object, shadow_list); 1210de5f6a77SJohn Dyson --object->backing_object->shadow_count; 121124a1cce3SDavid Greenman vm_object_reference(object->backing_object = backing_object->backing_object); 1212de5f6a77SJohn Dyson if (object->backing_object) { 121324a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&object->backing_object->shadow_head, 121424a1cce3SDavid Greenman object, shadow_list); 1215de5f6a77SJohn Dyson ++object->backing_object->shadow_count; 1216de5f6a77SJohn Dyson } 121724a1cce3SDavid Greenman object->backing_object_offset += backing_object->backing_object_offset; 1218df8bae1dSRodney W. Grimes 1219df8bae1dSRodney W. Grimes /* 12200d94caffSDavid Greenman * Drop the reference count on backing_object. Since 12210d94caffSDavid Greenman * its ref_count was at least 2, it will not vanish; 12220d94caffSDavid Greenman * so we don't need to call vm_object_deallocate. 1223df8bae1dSRodney W. Grimes */ 122426f9a767SRodney W. Grimes if (backing_object->ref_count == 1) 122526f9a767SRodney W. Grimes printf("should have called obj deallocate\n"); 1226df8bae1dSRodney W. Grimes backing_object->ref_count--; 1227df8bae1dSRodney W. Grimes 1228df8bae1dSRodney W. Grimes object_bypasses++; 1229df8bae1dSRodney W. Grimes 1230df8bae1dSRodney W. Grimes } 1231df8bae1dSRodney W. Grimes 1232df8bae1dSRodney W. Grimes /* 1233df8bae1dSRodney W. Grimes * Try again with this object's new backing object. 1234df8bae1dSRodney W. Grimes */ 1235df8bae1dSRodney W. Grimes } 1236df8bae1dSRodney W. Grimes } 1237df8bae1dSRodney W. Grimes 1238df8bae1dSRodney W. Grimes /* 1239df8bae1dSRodney W. Grimes * vm_object_page_remove: [internal] 1240df8bae1dSRodney W. Grimes * 1241df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 1242df8bae1dSRodney W. Grimes * object range from the object's list of pages. 1243df8bae1dSRodney W. Grimes * 1244df8bae1dSRodney W. Grimes * The object must be locked. 1245df8bae1dSRodney W. Grimes */ 124626f9a767SRodney W. Grimes void 12477c1f6cedSDavid Greenman vm_object_page_remove(object, start, end, clean_only) 1248df8bae1dSRodney W. Grimes register vm_object_t object; 1249a316d390SJohn Dyson register vm_pindex_t start; 1250a316d390SJohn Dyson register vm_pindex_t end; 12517c1f6cedSDavid Greenman boolean_t clean_only; 1252df8bae1dSRodney W. Grimes { 1253df8bae1dSRodney W. Grimes register vm_page_t p, next; 1254a316d390SJohn Dyson unsigned int size; 125526f9a767SRodney W. Grimes int s; 1256df8bae1dSRodney W. Grimes 1257df8bae1dSRodney W. Grimes if (object == NULL) 1258df8bae1dSRodney W. Grimes return; 1259df8bae1dSRodney W. Grimes 12602fe6e4d7SDavid Greenman object->paging_in_progress++; 126126f9a767SRodney W. Grimes again: 126226f9a767SRodney W. Grimes size = end - start; 1263a316d390SJohn Dyson if (size > 4 || size >= object->size / 4) { 1264b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 1265b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 12660891ef4cSJohn Dyson if ((start <= p->pindex) && (p->pindex < end)) { 1267bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1268bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1269bd7e5f99SJohn Dyson p->valid = 0; 12700d94caffSDavid Greenman continue; 12710d94caffSDavid Greenman } 12720891ef4cSJohn Dyson 1273b18bfc3dSJohn Dyson /* 1274b18bfc3dSJohn Dyson * The busy flags are only cleared at 1275b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1276b18bfc3dSJohn Dyson */ 1277b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1278b18bfc3dSJohn Dyson s = splvm(); 12790d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 128026f9a767SRodney W. Grimes p->flags |= PG_WANTED; 128124a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1282a481f200SDavid Greenman splx(s); 128326f9a767SRodney W. Grimes goto again; 128426f9a767SRodney W. Grimes } 1285a481f200SDavid Greenman splx(s); 1286b18bfc3dSJohn Dyson } 12870891ef4cSJohn Dyson 12887c1f6cedSDavid Greenman if (clean_only) { 12897c1f6cedSDavid Greenman vm_page_test_dirty(p); 12907c1f6cedSDavid Greenman if (p->valid & p->dirty) 12917c1f6cedSDavid Greenman continue; 12927c1f6cedSDavid Greenman } 1293f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 12940d94caffSDavid Greenman PAGE_WAKEUP(p); 1295df8bae1dSRodney W. Grimes vm_page_free(p); 129626f9a767SRodney W. Grimes } 129726f9a767SRodney W. Grimes } 129826f9a767SRodney W. Grimes } else { 129926f9a767SRodney W. Grimes while (size > 0) { 1300bd7e5f99SJohn Dyson if ((p = vm_page_lookup(object, start)) != 0) { 1301bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1302bd7e5f99SJohn Dyson p->valid = 0; 1303bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1304bd7e5f99SJohn Dyson start += 1; 1305bd7e5f99SJohn Dyson size -= 1; 1306bd7e5f99SJohn Dyson continue; 13070d94caffSDavid Greenman } 1308b18bfc3dSJohn Dyson /* 1309b18bfc3dSJohn Dyson * The busy flags are only cleared at 1310b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1311b18bfc3dSJohn Dyson */ 1312b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1313b18bfc3dSJohn Dyson s = splvm(); 13140d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 131526f9a767SRodney W. Grimes p->flags |= PG_WANTED; 131624a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1317a481f200SDavid Greenman splx(s); 131826f9a767SRodney W. Grimes goto again; 131926f9a767SRodney W. Grimes } 1320a481f200SDavid Greenman splx(s); 1321b18bfc3dSJohn Dyson } 13227c1f6cedSDavid Greenman if (clean_only) { 13237c1f6cedSDavid Greenman vm_page_test_dirty(p); 1324bd7e5f99SJohn Dyson if (p->valid & p->dirty) { 1325bd7e5f99SJohn Dyson start += 1; 1326bd7e5f99SJohn Dyson size -= 1; 13277c1f6cedSDavid Greenman continue; 13287c1f6cedSDavid Greenman } 1329bd7e5f99SJohn Dyson } 1330f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 13310d94caffSDavid Greenman PAGE_WAKEUP(p); 133226f9a767SRodney W. Grimes vm_page_free(p); 133326f9a767SRodney W. Grimes } 1334a316d390SJohn Dyson start += 1; 1335a316d390SJohn Dyson size -= 1; 1336df8bae1dSRodney W. Grimes } 1337df8bae1dSRodney W. Grimes } 1338f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1339c0503609SDavid Greenman } 1340df8bae1dSRodney W. Grimes 1341df8bae1dSRodney W. Grimes /* 1342df8bae1dSRodney W. Grimes * Routine: vm_object_coalesce 1343df8bae1dSRodney W. Grimes * Function: Coalesces two objects backing up adjoining 1344df8bae1dSRodney W. Grimes * regions of memory into a single object. 1345df8bae1dSRodney W. Grimes * 1346df8bae1dSRodney W. Grimes * returns TRUE if objects were combined. 1347df8bae1dSRodney W. Grimes * 1348df8bae1dSRodney W. Grimes * NOTE: Only works at the moment if the second object is NULL - 1349df8bae1dSRodney W. Grimes * if it's not, which object do we lock first? 1350df8bae1dSRodney W. Grimes * 1351df8bae1dSRodney W. Grimes * Parameters: 1352df8bae1dSRodney W. Grimes * prev_object First object to coalesce 1353df8bae1dSRodney W. Grimes * prev_offset Offset into prev_object 1354df8bae1dSRodney W. Grimes * next_object Second object into coalesce 1355df8bae1dSRodney W. Grimes * next_offset Offset into next_object 1356df8bae1dSRodney W. Grimes * 1357df8bae1dSRodney W. Grimes * prev_size Size of reference to prev_object 1358df8bae1dSRodney W. Grimes * next_size Size of reference to next_object 1359df8bae1dSRodney W. Grimes * 1360df8bae1dSRodney W. Grimes * Conditions: 1361df8bae1dSRodney W. Grimes * The object must *not* be locked. 1362df8bae1dSRodney W. Grimes */ 13630d94caffSDavid Greenman boolean_t 1364a316d390SJohn Dyson vm_object_coalesce(prev_object, prev_pindex, prev_size, next_size) 1365df8bae1dSRodney W. Grimes register vm_object_t prev_object; 1366a316d390SJohn Dyson vm_pindex_t prev_pindex; 1367df8bae1dSRodney W. Grimes vm_size_t prev_size, next_size; 1368df8bae1dSRodney W. Grimes { 1369df8bae1dSRodney W. Grimes vm_size_t newsize; 1370df8bae1dSRodney W. Grimes 1371df8bae1dSRodney W. Grimes if (prev_object == NULL) { 1372df8bae1dSRodney W. Grimes return (TRUE); 1373df8bae1dSRodney W. Grimes } 1374df8bae1dSRodney W. Grimes 137530dcfc09SJohn Dyson if (prev_object->type != OBJT_DEFAULT) { 137630dcfc09SJohn Dyson return (FALSE); 137730dcfc09SJohn Dyson } 137830dcfc09SJohn Dyson 1379df8bae1dSRodney W. Grimes /* 1380df8bae1dSRodney W. Grimes * Try to collapse the object first 1381df8bae1dSRodney W. Grimes */ 1382df8bae1dSRodney W. Grimes vm_object_collapse(prev_object); 1383df8bae1dSRodney W. Grimes 1384df8bae1dSRodney W. Grimes /* 13850d94caffSDavid Greenman * Can't coalesce if: . more than one reference . paged out . shadows 13860d94caffSDavid Greenman * another object . has a copy elsewhere (any of which mean that the 13870d94caffSDavid Greenman * pages not mapped to prev_entry may be in use anyway) 1388df8bae1dSRodney W. Grimes */ 1389df8bae1dSRodney W. Grimes 13908cc7e047SJohn Dyson if (prev_object->backing_object != NULL) { 1391df8bae1dSRodney W. Grimes return (FALSE); 1392df8bae1dSRodney W. Grimes } 1393a316d390SJohn Dyson 1394a316d390SJohn Dyson prev_size >>= PAGE_SHIFT; 1395a316d390SJohn Dyson next_size >>= PAGE_SHIFT; 13968cc7e047SJohn Dyson 13978cc7e047SJohn Dyson if ((prev_object->ref_count > 1) && 13988cc7e047SJohn Dyson (prev_object->size != prev_pindex + prev_size)) { 13998cc7e047SJohn Dyson return (FALSE); 14008cc7e047SJohn Dyson } 14018cc7e047SJohn Dyson 1402df8bae1dSRodney W. Grimes /* 14030d94caffSDavid Greenman * Remove any pages that may still be in the object from a previous 14040d94caffSDavid Greenman * deallocation. 1405df8bae1dSRodney W. Grimes */ 1406df8bae1dSRodney W. Grimes 1407df8bae1dSRodney W. Grimes vm_object_page_remove(prev_object, 1408a316d390SJohn Dyson prev_pindex + prev_size, 1409a316d390SJohn Dyson prev_pindex + prev_size + next_size, FALSE); 1410df8bae1dSRodney W. Grimes 1411df8bae1dSRodney W. Grimes /* 1412df8bae1dSRodney W. Grimes * Extend the object if necessary. 1413df8bae1dSRodney W. Grimes */ 1414a316d390SJohn Dyson newsize = prev_pindex + prev_size + next_size; 1415df8bae1dSRodney W. Grimes if (newsize > prev_object->size) 1416df8bae1dSRodney W. Grimes prev_object->size = newsize; 1417df8bae1dSRodney W. Grimes 1418df8bae1dSRodney W. Grimes return (TRUE); 1419df8bae1dSRodney W. Grimes } 1420df8bae1dSRodney W. Grimes 1421c7c34a24SBruce Evans #include "opt_ddb.h" 1422c3cb3e12SDavid Greenman #ifdef DDB 1423c7c34a24SBruce Evans #include <sys/kernel.h> 1424c7c34a24SBruce Evans 1425c7c34a24SBruce Evans #include <machine/cons.h> 1426c7c34a24SBruce Evans 1427c7c34a24SBruce Evans #include <ddb/ddb.h> 1428c7c34a24SBruce Evans 1429c7c34a24SBruce Evans static int _vm_object_in_map __P((vm_map_t map, vm_object_t object, 1430c7c34a24SBruce Evans vm_map_entry_t entry)); 1431c7c34a24SBruce Evans static int vm_object_in_map __P((vm_object_t object)); 1432c3cb3e12SDavid Greenman 1433cac597e4SBruce Evans static int 1434a1f6d91cSDavid Greenman _vm_object_in_map(map, object, entry) 1435a1f6d91cSDavid Greenman vm_map_t map; 1436a1f6d91cSDavid Greenman vm_object_t object; 1437a1f6d91cSDavid Greenman vm_map_entry_t entry; 1438a1f6d91cSDavid Greenman { 1439a1f6d91cSDavid Greenman vm_map_t tmpm; 1440a1f6d91cSDavid Greenman vm_map_entry_t tmpe; 1441a1f6d91cSDavid Greenman vm_object_t obj; 1442a1f6d91cSDavid Greenman int entcount; 1443a1f6d91cSDavid Greenman 1444a1f6d91cSDavid Greenman if (map == 0) 1445a1f6d91cSDavid Greenman return 0; 1446a1f6d91cSDavid Greenman 1447a1f6d91cSDavid Greenman if (entry == 0) { 1448a1f6d91cSDavid Greenman tmpe = map->header.next; 1449a1f6d91cSDavid Greenman entcount = map->nentries; 1450a1f6d91cSDavid Greenman while (entcount-- && (tmpe != &map->header)) { 1451a1f6d91cSDavid Greenman if( _vm_object_in_map(map, object, tmpe)) { 1452a1f6d91cSDavid Greenman return 1; 1453a1f6d91cSDavid Greenman } 1454a1f6d91cSDavid Greenman tmpe = tmpe->next; 1455a1f6d91cSDavid Greenman } 1456afa07f7eSJohn Dyson } else if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { 1457a1f6d91cSDavid Greenman tmpm = entry->object.share_map; 1458a1f6d91cSDavid Greenman tmpe = tmpm->header.next; 1459a1f6d91cSDavid Greenman entcount = tmpm->nentries; 1460a1f6d91cSDavid Greenman while (entcount-- && tmpe != &tmpm->header) { 1461a1f6d91cSDavid Greenman if( _vm_object_in_map(tmpm, object, tmpe)) { 1462a1f6d91cSDavid Greenman return 1; 1463a1f6d91cSDavid Greenman } 1464a1f6d91cSDavid Greenman tmpe = tmpe->next; 1465a1f6d91cSDavid Greenman } 1466a1f6d91cSDavid Greenman } else if (obj = entry->object.vm_object) { 146724a1cce3SDavid Greenman for(; obj; obj=obj->backing_object) 1468a1f6d91cSDavid Greenman if( obj == object) { 1469a1f6d91cSDavid Greenman return 1; 1470a1f6d91cSDavid Greenman } 1471a1f6d91cSDavid Greenman } 1472a1f6d91cSDavid Greenman return 0; 1473a1f6d91cSDavid Greenman } 1474a1f6d91cSDavid Greenman 1475cac597e4SBruce Evans static int 1476a1f6d91cSDavid Greenman vm_object_in_map( object) 1477a1f6d91cSDavid Greenman vm_object_t object; 1478a1f6d91cSDavid Greenman { 1479a1f6d91cSDavid Greenman struct proc *p; 14801b67ec6dSJeffrey Hsu for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 1481a1f6d91cSDavid Greenman if( !p->p_vmspace /* || (p->p_flag & (P_SYSTEM|P_WEXIT)) */) 1482a1f6d91cSDavid Greenman continue; 1483a1f6d91cSDavid Greenman if( _vm_object_in_map(&p->p_vmspace->vm_map, object, 0)) 1484a1f6d91cSDavid Greenman return 1; 1485a1f6d91cSDavid Greenman } 1486a1f6d91cSDavid Greenman if( _vm_object_in_map( kernel_map, object, 0)) 1487a1f6d91cSDavid Greenman return 1; 1488a1f6d91cSDavid Greenman if( _vm_object_in_map( kmem_map, object, 0)) 1489a1f6d91cSDavid Greenman return 1; 1490a1f6d91cSDavid Greenman if( _vm_object_in_map( pager_map, object, 0)) 1491a1f6d91cSDavid Greenman return 1; 1492a1f6d91cSDavid Greenman if( _vm_object_in_map( buffer_map, object, 0)) 1493a1f6d91cSDavid Greenman return 1; 1494a1f6d91cSDavid Greenman if( _vm_object_in_map( io_map, object, 0)) 1495a1f6d91cSDavid Greenman return 1; 1496a1f6d91cSDavid Greenman if( _vm_object_in_map( phys_map, object, 0)) 1497a1f6d91cSDavid Greenman return 1; 1498a1f6d91cSDavid Greenman if( _vm_object_in_map( mb_map, object, 0)) 1499a1f6d91cSDavid Greenman return 1; 1500a1f6d91cSDavid Greenman if( _vm_object_in_map( u_map, object, 0)) 1501a1f6d91cSDavid Greenman return 1; 1502a1f6d91cSDavid Greenman return 0; 1503a1f6d91cSDavid Greenman } 1504a1f6d91cSDavid Greenman 1505c7c34a24SBruce Evans DB_SHOW_COMMAND(vmochk, vm_object_check) 1506f708ef1bSPoul-Henning Kamp { 1507a1f6d91cSDavid Greenman vm_object_t object; 1508a1f6d91cSDavid Greenman 1509a1f6d91cSDavid Greenman /* 1510a1f6d91cSDavid Greenman * make sure that internal objs are in a map somewhere 1511a1f6d91cSDavid Greenman * and none have zero ref counts. 1512a1f6d91cSDavid Greenman */ 1513b18bfc3dSJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 1514a1f6d91cSDavid Greenman object != NULL; 1515b18bfc3dSJohn Dyson object = TAILQ_NEXT(object, object_list)) { 151624a1cce3SDavid Greenman if (object->handle == NULL && 151724a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { 1518a1f6d91cSDavid Greenman if (object->ref_count == 0) { 1519c7c34a24SBruce Evans db_printf("vmochk: internal obj has zero ref count: %d\n", 1520a1f6d91cSDavid Greenman object->size); 1521a1f6d91cSDavid Greenman } 1522a1f6d91cSDavid Greenman if (!vm_object_in_map(object)) { 1523c7c34a24SBruce Evans db_printf("vmochk: internal obj is not in a map: " 15243af76890SPoul-Henning Kamp "ref: %d, size: %d: 0x%x, backing_object: 0x%x\n", 15253af76890SPoul-Henning Kamp object->ref_count, object->size, 15263af76890SPoul-Henning Kamp object->size, object->backing_object); 1527a1f6d91cSDavid Greenman } 1528a1f6d91cSDavid Greenman } 1529a1f6d91cSDavid Greenman } 1530a1f6d91cSDavid Greenman } 1531a1f6d91cSDavid Greenman 153226f9a767SRodney W. Grimes /* 1533df8bae1dSRodney W. Grimes * vm_object_print: [ debug ] 1534df8bae1dSRodney W. Grimes */ 1535c7c34a24SBruce Evans DB_SHOW_COMMAND(object, vm_object_print_static) 1536df8bae1dSRodney W. Grimes { 1537c7c34a24SBruce Evans /* XXX convert args. */ 1538c7c34a24SBruce Evans vm_object_t object = (vm_object_t)addr; 1539c7c34a24SBruce Evans boolean_t full = have_addr; 1540c7c34a24SBruce Evans 1541df8bae1dSRodney W. Grimes register vm_page_t p; 1542df8bae1dSRodney W. Grimes 1543c7c34a24SBruce Evans /* XXX count is an (unused) arg. Avoid shadowing it. */ 1544c7c34a24SBruce Evans #define count was_count 1545c7c34a24SBruce Evans 1546df8bae1dSRodney W. Grimes register int count; 1547df8bae1dSRodney W. Grimes 1548df8bae1dSRodney W. Grimes if (object == NULL) 1549df8bae1dSRodney W. Grimes return; 1550df8bae1dSRodney W. Grimes 1551c7c34a24SBruce Evans db_iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ", 1552df8bae1dSRodney W. Grimes (int) object, (int) object->size, 1553df8bae1dSRodney W. Grimes object->resident_page_count, object->ref_count); 1554c7c34a24SBruce Evans db_printf("offset=0x%x, backing_object=(0x%x)+0x%x\n", 15552a4895f4SDavid Greenman (int) object->paging_offset, 155624a1cce3SDavid Greenman (int) object->backing_object, (int) object->backing_object_offset); 1557c7c34a24SBruce Evans db_printf("cache: next=%p, prev=%p\n", 1558b18bfc3dSJohn Dyson TAILQ_NEXT(object, cached_list), TAILQ_PREV(object, cached_list)); 1559df8bae1dSRodney W. Grimes 1560df8bae1dSRodney W. Grimes if (!full) 1561df8bae1dSRodney W. Grimes return; 1562df8bae1dSRodney W. Grimes 1563c7c34a24SBruce Evans db_indent += 2; 1564df8bae1dSRodney W. Grimes count = 0; 1565b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { 1566df8bae1dSRodney W. Grimes if (count == 0) 1567c7c34a24SBruce Evans db_iprintf("memory:="); 1568df8bae1dSRodney W. Grimes else if (count == 6) { 1569c7c34a24SBruce Evans db_printf("\n"); 1570c7c34a24SBruce Evans db_iprintf(" ..."); 1571df8bae1dSRodney W. Grimes count = 0; 1572df8bae1dSRodney W. Grimes } else 1573c7c34a24SBruce Evans db_printf(","); 1574df8bae1dSRodney W. Grimes count++; 1575df8bae1dSRodney W. Grimes 1576c7c34a24SBruce Evans db_printf("(off=0x%lx,page=0x%lx)", 1577a316d390SJohn Dyson (u_long) p->pindex, (u_long) VM_PAGE_TO_PHYS(p)); 1578df8bae1dSRodney W. Grimes } 1579df8bae1dSRodney W. Grimes if (count != 0) 1580c7c34a24SBruce Evans db_printf("\n"); 1581c7c34a24SBruce Evans db_indent -= 2; 1582df8bae1dSRodney W. Grimes } 15835070c7f8SJohn Dyson 1584c7c34a24SBruce Evans /* XXX. */ 1585c7c34a24SBruce Evans #undef count 1586c7c34a24SBruce Evans 1587c7c34a24SBruce Evans /* XXX need this non-static entry for calling from vm_map_print. */ 15885070c7f8SJohn Dyson void 1589c7c34a24SBruce Evans vm_object_print(addr, have_addr, count, modif) 1590c7c34a24SBruce Evans db_expr_t addr; 1591c7c34a24SBruce Evans boolean_t have_addr; 1592c7c34a24SBruce Evans db_expr_t count; 1593c7c34a24SBruce Evans char *modif; 1594c7c34a24SBruce Evans { 1595c7c34a24SBruce Evans vm_object_print_static(addr, have_addr, count, modif); 1596c7c34a24SBruce Evans } 1597c7c34a24SBruce Evans 1598c7c34a24SBruce Evans DB_SHOW_COMMAND(vmopag, vm_object_print_pages) 15995070c7f8SJohn Dyson { 16005070c7f8SJohn Dyson vm_object_t object; 16015070c7f8SJohn Dyson int nl = 0; 16025070c7f8SJohn Dyson int c; 16035070c7f8SJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 16045070c7f8SJohn Dyson object != NULL; 16055070c7f8SJohn Dyson object = TAILQ_NEXT(object, object_list)) { 16065070c7f8SJohn Dyson vm_pindex_t idx, fidx; 16075070c7f8SJohn Dyson vm_pindex_t osize; 16085070c7f8SJohn Dyson vm_offset_t pa = -1, padiff; 16095070c7f8SJohn Dyson int rcount; 16105070c7f8SJohn Dyson vm_page_t m; 16115070c7f8SJohn Dyson 16125070c7f8SJohn Dyson db_printf("new object: 0x%x\n", object); 16135070c7f8SJohn Dyson if ( nl > 18) { 16145070c7f8SJohn Dyson c = cngetc(); 16155070c7f8SJohn Dyson if (c != ' ') 16165070c7f8SJohn Dyson return; 16175070c7f8SJohn Dyson nl = 0; 16185070c7f8SJohn Dyson } 16195070c7f8SJohn Dyson nl++; 16205070c7f8SJohn Dyson rcount = 0; 16215070c7f8SJohn Dyson fidx = 0; 16225070c7f8SJohn Dyson osize = object->size; 16235070c7f8SJohn Dyson if (osize > 128) 16245070c7f8SJohn Dyson osize = 128; 16255070c7f8SJohn Dyson for(idx=0;idx<osize;idx++) { 16265070c7f8SJohn Dyson m = vm_page_lookup(object, idx); 16275070c7f8SJohn Dyson if (m == NULL) { 16285070c7f8SJohn Dyson if (rcount) { 16295070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", 16305070c7f8SJohn Dyson fidx, rcount, pa); 16315070c7f8SJohn Dyson if ( nl > 18) { 16325070c7f8SJohn Dyson c = cngetc(); 16335070c7f8SJohn Dyson if (c != ' ') 16345070c7f8SJohn Dyson return; 16355070c7f8SJohn Dyson nl = 0; 16365070c7f8SJohn Dyson } 16375070c7f8SJohn Dyson nl++; 16385070c7f8SJohn Dyson rcount = 0; 16395070c7f8SJohn Dyson } 16405070c7f8SJohn Dyson continue; 16415070c7f8SJohn Dyson } 16425070c7f8SJohn Dyson 16435070c7f8SJohn Dyson 16445070c7f8SJohn Dyson if (rcount && 16455070c7f8SJohn Dyson (VM_PAGE_TO_PHYS(m) == pa + rcount * PAGE_SIZE)) { 16465070c7f8SJohn Dyson ++rcount; 16475070c7f8SJohn Dyson continue; 16485070c7f8SJohn Dyson } 16495070c7f8SJohn Dyson if (rcount) { 16505070c7f8SJohn Dyson padiff = pa + rcount * PAGE_SIZE - VM_PAGE_TO_PHYS(m); 16515070c7f8SJohn Dyson padiff >>= PAGE_SHIFT; 16525070c7f8SJohn Dyson padiff &= PQ_L2_MASK; 16535070c7f8SJohn Dyson if (padiff == 0) { 16545070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m) - rcount * PAGE_SIZE; 16555070c7f8SJohn Dyson ++rcount; 16565070c7f8SJohn Dyson continue; 16575070c7f8SJohn Dyson } 16585070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)", fidx, rcount, pa); 16595070c7f8SJohn Dyson db_printf("pd(%d)\n", padiff); 16605070c7f8SJohn Dyson if ( nl > 18) { 16615070c7f8SJohn Dyson c = cngetc(); 16625070c7f8SJohn Dyson if (c != ' ') 16635070c7f8SJohn Dyson return; 16645070c7f8SJohn Dyson nl = 0; 16655070c7f8SJohn Dyson } 16665070c7f8SJohn Dyson nl++; 16675070c7f8SJohn Dyson } 16685070c7f8SJohn Dyson fidx = idx; 16695070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m); 16705070c7f8SJohn Dyson rcount = 1; 16715070c7f8SJohn Dyson } 16725070c7f8SJohn Dyson if (rcount) { 16735070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", fidx, rcount, pa); 16745070c7f8SJohn Dyson if ( nl > 18) { 16755070c7f8SJohn Dyson c = cngetc(); 16765070c7f8SJohn Dyson if (c != ' ') 16775070c7f8SJohn Dyson return; 16785070c7f8SJohn Dyson nl = 0; 16795070c7f8SJohn Dyson } 16805070c7f8SJohn Dyson nl++; 16815070c7f8SJohn Dyson } 16825070c7f8SJohn Dyson } 16835070c7f8SJohn Dyson } 1684c3cb3e12SDavid Greenman #endif /* DDB */ 1685