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 * 641130b656SJordan K. Hubbard * $FreeBSD$ 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/kernel.h> 74f23b4c91SGarrett Wollman #include <sys/proc.h> /* for curproc, pageproc */ 75df8bae1dSRodney W. Grimes #include <sys/malloc.h> 760d94caffSDavid Greenman #include <sys/vnode.h> 770d94caffSDavid Greenman #include <sys/mount.h> 78efeaf95aSDavid Greenman #include <sys/vmmeter.h> 79867a482dSJohn Dyson #include <sys/mman.h> 80df8bae1dSRodney W. Grimes 81df8bae1dSRodney W. Grimes #include <vm/vm.h> 82efeaf95aSDavid Greenman #include <vm/vm_param.h> 83efeaf95aSDavid Greenman #include <vm/vm_prot.h> 84996c772fSJohn Dyson #include <sys/lock.h> 85efeaf95aSDavid Greenman #include <vm/pmap.h> 86efeaf95aSDavid Greenman #include <vm/vm_map.h> 87efeaf95aSDavid Greenman #include <vm/vm_object.h> 88df8bae1dSRodney W. Grimes #include <vm/vm_page.h> 8926f9a767SRodney W. Grimes #include <vm/vm_pageout.h> 900d94caffSDavid Greenman #include <vm/vm_pager.h> 9105f0fdd2SPoul-Henning Kamp #include <vm/swap_pager.h> 92a1f6d91cSDavid Greenman #include <vm/vm_kern.h> 93efeaf95aSDavid Greenman #include <vm/vm_extern.h> 9426f9a767SRodney W. Grimes 95cac597e4SBruce Evans static void _vm_object_allocate __P((objtype_t, vm_size_t, vm_object_t)); 96cac597e4SBruce Evans static void vm_object_qcollapse __P((vm_object_t object)); 97f708ef1bSPoul-Henning Kamp #ifdef not_used 98f708ef1bSPoul-Henning Kamp static void vm_object_deactivate_pages __P((vm_object_t)); 99f708ef1bSPoul-Henning Kamp #endif 100f708ef1bSPoul-Henning Kamp static void vm_object_terminate __P((vm_object_t)); 101f708ef1bSPoul-Henning Kamp static void vm_object_cache_trim __P((void)); 102f6b04d2bSDavid Greenman 103df8bae1dSRodney W. Grimes /* 104df8bae1dSRodney W. Grimes * Virtual memory objects maintain the actual data 105df8bae1dSRodney W. Grimes * associated with allocated virtual memory. A given 106df8bae1dSRodney W. Grimes * page of memory exists within exactly one object. 107df8bae1dSRodney W. Grimes * 108df8bae1dSRodney W. Grimes * An object is only deallocated when all "references" 109df8bae1dSRodney W. Grimes * are given up. Only one "reference" to a given 110df8bae1dSRodney W. Grimes * region of an object should be writeable. 111df8bae1dSRodney W. Grimes * 112df8bae1dSRodney W. Grimes * Associated with each object is a list of all resident 113df8bae1dSRodney W. Grimes * memory pages belonging to that object; this list is 114df8bae1dSRodney W. Grimes * maintained by the "vm_page" module, and locked by the object's 115df8bae1dSRodney W. Grimes * lock. 116df8bae1dSRodney W. Grimes * 117df8bae1dSRodney W. Grimes * Each object also records a "pager" routine which is 118df8bae1dSRodney W. Grimes * used to retrieve (and store) pages to the proper backing 119df8bae1dSRodney W. Grimes * storage. In addition, objects may be backed by other 120df8bae1dSRodney W. Grimes * objects from which they were virtual-copied. 121df8bae1dSRodney W. Grimes * 122df8bae1dSRodney W. Grimes * The only items within the object structure which are 123df8bae1dSRodney W. Grimes * modified after time of creation are: 124df8bae1dSRodney W. Grimes * reference count locked by object's lock 125df8bae1dSRodney W. Grimes * pager routine locked by object's lock 126df8bae1dSRodney W. Grimes * 127df8bae1dSRodney W. Grimes */ 128df8bae1dSRodney W. Grimes 12928f8db14SBruce Evans int vm_object_cache_max; 13028f8db14SBruce Evans struct object_q vm_object_cached_list; 131f708ef1bSPoul-Henning Kamp static int vm_object_cached; 13228f8db14SBruce Evans struct object_q vm_object_list; 133996c772fSJohn Dyson struct simplelock vm_object_list_lock; 134f708ef1bSPoul-Henning Kamp static long vm_object_count; 13528f8db14SBruce Evans vm_object_t kernel_object; 13628f8db14SBruce Evans vm_object_t kmem_object; 137f708ef1bSPoul-Henning Kamp static struct vm_object kernel_object_store; 138f708ef1bSPoul-Henning Kamp static struct vm_object kmem_object_store; 139aef922f5SJohn Dyson extern int vm_pageout_page_count; 140df8bae1dSRodney W. Grimes 141f708ef1bSPoul-Henning Kamp static long object_collapses; 142f708ef1bSPoul-Henning Kamp static long object_bypasses; 1435070c7f8SJohn Dyson static int next_index; 144df8bae1dSRodney W. Grimes 145df8bae1dSRodney W. Grimes static void 14624a1cce3SDavid Greenman _vm_object_allocate(type, size, object) 14724a1cce3SDavid Greenman objtype_t type; 148df8bae1dSRodney W. Grimes vm_size_t size; 149df8bae1dSRodney W. Grimes register vm_object_t object; 150df8bae1dSRodney W. Grimes { 151df8bae1dSRodney W. Grimes TAILQ_INIT(&object->memq); 15224a1cce3SDavid Greenman TAILQ_INIT(&object->shadow_head); 153a1f6d91cSDavid Greenman 15424a1cce3SDavid Greenman object->type = type; 155df8bae1dSRodney W. Grimes object->size = size; 156a1f6d91cSDavid Greenman object->ref_count = 1; 15724a1cce3SDavid Greenman object->flags = 0; 158867a482dSJohn Dyson object->behavior = OBJ_NORMAL; 159df8bae1dSRodney W. Grimes object->paging_in_progress = 0; 160a1f6d91cSDavid Greenman object->resident_page_count = 0; 161de5f6a77SJohn Dyson object->shadow_count = 0; 1625070c7f8SJohn Dyson object->pg_color = next_index; 1635070c7f8SJohn Dyson next_index = (next_index + PQ_PRIME1) & PQ_L2_MASK; 16424a1cce3SDavid Greenman object->handle = NULL; 165a316d390SJohn Dyson object->paging_offset = (vm_ooffset_t) 0; 16624a1cce3SDavid Greenman object->backing_object = NULL; 167a316d390SJohn Dyson object->backing_object_offset = (vm_ooffset_t) 0; 168a2f4a846SJohn Dyson object->page_hint = NULL; 169a1f6d91cSDavid Greenman 170a1f6d91cSDavid Greenman object->last_read = 0; 171df8bae1dSRodney W. Grimes 172df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&vm_object_list, object, object_list); 173df8bae1dSRodney W. Grimes vm_object_count++; 174df8bae1dSRodney W. Grimes } 175df8bae1dSRodney W. Grimes 176df8bae1dSRodney W. Grimes /* 17726f9a767SRodney W. Grimes * vm_object_init: 17826f9a767SRodney W. Grimes * 17926f9a767SRodney W. Grimes * Initialize the VM objects module. 18026f9a767SRodney W. Grimes */ 18126f9a767SRodney W. Grimes void 182a316d390SJohn Dyson vm_object_init() 18326f9a767SRodney W. Grimes { 18426f9a767SRodney W. Grimes TAILQ_INIT(&vm_object_cached_list); 18526f9a767SRodney W. Grimes TAILQ_INIT(&vm_object_list); 186996c772fSJohn Dyson simple_lock_init(&vm_object_list_lock); 18726f9a767SRodney W. Grimes vm_object_count = 0; 1880217125fSDavid Greenman 1890217125fSDavid Greenman vm_object_cache_max = 84; 1900217125fSDavid Greenman if (cnt.v_page_count > 1000) 19146268a60SDavid Greenman vm_object_cache_max += (cnt.v_page_count - 1000) / 4; 19226f9a767SRodney W. Grimes 19326f9a767SRodney W. Grimes kernel_object = &kernel_object_store; 194a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 19526f9a767SRodney W. Grimes kernel_object); 19626f9a767SRodney W. Grimes 19726f9a767SRodney W. Grimes kmem_object = &kmem_object_store; 198a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 19926f9a767SRodney W. Grimes kmem_object); 20026f9a767SRodney W. Grimes } 20126f9a767SRodney W. Grimes 20226f9a767SRodney W. Grimes /* 20326f9a767SRodney W. Grimes * vm_object_allocate: 20426f9a767SRodney W. Grimes * 20526f9a767SRodney W. Grimes * Returns a new object with the given size. 20626f9a767SRodney W. Grimes */ 20726f9a767SRodney W. Grimes 20826f9a767SRodney W. Grimes vm_object_t 20924a1cce3SDavid Greenman vm_object_allocate(type, size) 21024a1cce3SDavid Greenman objtype_t type; 21126f9a767SRodney W. Grimes vm_size_t size; 21226f9a767SRodney W. Grimes { 21326f9a767SRodney W. Grimes register vm_object_t result; 21426f9a767SRodney W. Grimes 21526f9a767SRodney W. Grimes result = (vm_object_t) 21626f9a767SRodney W. Grimes malloc((u_long) sizeof *result, M_VMOBJ, M_WAITOK); 21726f9a767SRodney W. Grimes 21867bf6868SJohn Dyson 21924a1cce3SDavid Greenman _vm_object_allocate(type, size, result); 22026f9a767SRodney W. Grimes 22126f9a767SRodney W. Grimes return (result); 22226f9a767SRodney W. Grimes } 22326f9a767SRodney W. Grimes 22426f9a767SRodney W. Grimes 22526f9a767SRodney W. Grimes /* 226df8bae1dSRodney W. Grimes * vm_object_reference: 227df8bae1dSRodney W. Grimes * 228df8bae1dSRodney W. Grimes * Gets another reference to the given object. 229df8bae1dSRodney W. Grimes */ 2306476c0d2SJohn Dyson void 23126f9a767SRodney W. Grimes vm_object_reference(object) 232df8bae1dSRodney W. Grimes register vm_object_t object; 233df8bae1dSRodney W. Grimes { 234df8bae1dSRodney W. Grimes if (object == NULL) 235df8bae1dSRodney W. Grimes return; 236df8bae1dSRodney W. Grimes 23724a1cce3SDavid Greenman if (object->ref_count == 0) { 23824a1cce3SDavid Greenman if ((object->flags & OBJ_CANPERSIST) == 0) 23924a1cce3SDavid Greenman panic("vm_object_reference: non-persistent object with 0 ref_count"); 24024a1cce3SDavid Greenman TAILQ_REMOVE(&vm_object_cached_list, object, cached_list); 24124a1cce3SDavid Greenman vm_object_cached--; 24224a1cce3SDavid Greenman } 243df8bae1dSRodney W. Grimes object->ref_count++; 244df8bae1dSRodney W. Grimes } 245df8bae1dSRodney W. Grimes 246df8bae1dSRodney W. Grimes /* 247df8bae1dSRodney W. Grimes * vm_object_deallocate: 248df8bae1dSRodney W. Grimes * 249df8bae1dSRodney W. Grimes * Release a reference to the specified object, 250df8bae1dSRodney W. Grimes * gained either through a vm_object_allocate 251df8bae1dSRodney W. Grimes * or a vm_object_reference call. When all references 252df8bae1dSRodney W. Grimes * are gone, storage associated with this object 253df8bae1dSRodney W. Grimes * may be relinquished. 254df8bae1dSRodney W. Grimes * 255df8bae1dSRodney W. Grimes * No object may be locked. 256df8bae1dSRodney W. Grimes */ 25726f9a767SRodney W. Grimes void 25826f9a767SRodney W. Grimes vm_object_deallocate(object) 25926f9a767SRodney W. Grimes vm_object_t object; 260df8bae1dSRodney W. Grimes { 261df8bae1dSRodney W. Grimes vm_object_t temp; 262df8bae1dSRodney W. Grimes 263df8bae1dSRodney W. Grimes while (object != NULL) { 264df8bae1dSRodney W. Grimes 265ba8da839SDavid Greenman if (object->ref_count == 0) 266ba8da839SDavid Greenman panic("vm_object_deallocate: object deallocated too many times"); 267ba8da839SDavid Greenman 268df8bae1dSRodney W. Grimes /* 269df8bae1dSRodney W. Grimes * Lose the reference 270df8bae1dSRodney W. Grimes */ 271be6d5bfaSDavid Greenman object->ref_count--; 272be6d5bfaSDavid Greenman if (object->ref_count != 0) { 273be6d5bfaSDavid Greenman if ((object->ref_count == 1) && 27424a1cce3SDavid Greenman (object->handle == NULL) && 27524a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || 27624a1cce3SDavid Greenman object->type == OBJT_SWAP)) { 277a1f6d91cSDavid Greenman vm_object_t robject; 278b18bfc3dSJohn Dyson robject = TAILQ_FIRST(&object->shadow_head); 279be6d5bfaSDavid Greenman if ((robject != NULL) && 28024a1cce3SDavid Greenman (robject->handle == NULL) && 28124a1cce3SDavid Greenman (robject->type == OBJT_DEFAULT || 28224a1cce3SDavid Greenman robject->type == OBJT_SWAP)) { 283a1f6d91cSDavid Greenman int s; 284a1f6d91cSDavid Greenman robject->ref_count += 2; 2859b4814bbSDavid Greenman object->ref_count += 2; 286a1f6d91cSDavid Greenman 287a1f6d91cSDavid Greenman do { 288b18bfc3dSJohn Dyson s = splvm(); 289a1f6d91cSDavid Greenman while (robject->paging_in_progress) { 290c0503609SDavid Greenman robject->flags |= OBJ_PIPWNT; 291a1f6d91cSDavid Greenman tsleep(robject, PVM, "objde1", 0); 2920d94caffSDavid Greenman } 293a1f6d91cSDavid Greenman 294a1f6d91cSDavid Greenman while (object->paging_in_progress) { 295c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 296a1f6d91cSDavid Greenman tsleep(object, PVM, "objde2", 0); 297a1f6d91cSDavid Greenman } 298a1f6d91cSDavid Greenman splx(s); 299a1f6d91cSDavid Greenman 300a1f6d91cSDavid Greenman } while( object->paging_in_progress || robject->paging_in_progress); 301a1f6d91cSDavid Greenman 3029b4814bbSDavid Greenman object->ref_count -= 2; 303a1f6d91cSDavid Greenman robject->ref_count -= 2; 304a1f6d91cSDavid Greenman if( robject->ref_count == 0) { 305a1f6d91cSDavid Greenman robject->ref_count += 1; 306ba8da839SDavid Greenman object = robject; 307ba8da839SDavid Greenman continue; 308a1f6d91cSDavid Greenman } 309a1f6d91cSDavid Greenman vm_object_collapse(robject); 310a1f6d91cSDavid Greenman return; 311010cf3b9SDavid Greenman } 312010cf3b9SDavid Greenman } 313df8bae1dSRodney W. Grimes /* 3140d94caffSDavid Greenman * If there are still references, then we are done. 315df8bae1dSRodney W. Grimes */ 316df8bae1dSRodney W. Grimes return; 317df8bae1dSRodney W. Grimes } 318df8bae1dSRodney W. Grimes 31924a1cce3SDavid Greenman if (object->type == OBJT_VNODE) { 32024a1cce3SDavid Greenman struct vnode *vp = object->handle; 321f5cf85d4SDavid Greenman 32224a1cce3SDavid Greenman vp->v_flag &= ~VTEXT; 323f5cf85d4SDavid Greenman } 324f5cf85d4SDavid Greenman 325f919ebdeSDavid Greenman /* 326f919ebdeSDavid Greenman * See if this object can persist and has some resident 327f919ebdeSDavid Greenman * pages. If so, enter it in the cache. 328f919ebdeSDavid Greenman */ 329f5cf85d4SDavid Greenman if (object->flags & OBJ_CANPERSIST) { 330f5cf85d4SDavid Greenman if (object->resident_page_count != 0) { 3316476c0d2SJohn Dyson #if 0 33224a1cce3SDavid Greenman vm_object_page_clean(object, 0, 0 ,TRUE, TRUE); 3336476c0d2SJohn Dyson #endif 334df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&vm_object_cached_list, object, 335df8bae1dSRodney W. Grimes cached_list); 336df8bae1dSRodney W. Grimes vm_object_cached++; 337df8bae1dSRodney W. Grimes 338df8bae1dSRodney W. Grimes vm_object_cache_trim(); 339df8bae1dSRodney W. Grimes return; 340f5cf85d4SDavid Greenman } else { 341f5cf85d4SDavid Greenman object->flags &= ~OBJ_CANPERSIST; 342f5cf85d4SDavid Greenman } 343df8bae1dSRodney W. Grimes } 344f919ebdeSDavid Greenman 345df8bae1dSRodney W. Grimes /* 34624a1cce3SDavid Greenman * Make sure no one uses us. 347df8bae1dSRodney W. Grimes */ 3480d94caffSDavid Greenman object->flags |= OBJ_DEAD; 349df8bae1dSRodney W. Grimes 35024a1cce3SDavid Greenman temp = object->backing_object; 351de5f6a77SJohn Dyson if (temp) { 35224a1cce3SDavid Greenman TAILQ_REMOVE(&temp->shadow_head, object, shadow_list); 353de5f6a77SJohn Dyson --temp->shadow_count; 354de5f6a77SJohn Dyson } 355df8bae1dSRodney W. Grimes vm_object_terminate(object); 356df8bae1dSRodney W. Grimes /* unlocks and deallocates object */ 357df8bae1dSRodney W. Grimes object = temp; 358df8bae1dSRodney W. Grimes } 359df8bae1dSRodney W. Grimes } 360df8bae1dSRodney W. Grimes 361df8bae1dSRodney W. Grimes /* 362df8bae1dSRodney W. Grimes * vm_object_terminate actually destroys the specified object, freeing 363df8bae1dSRodney W. Grimes * up all previously used resources. 364df8bae1dSRodney W. Grimes * 365df8bae1dSRodney W. Grimes * The object must be locked. 366df8bae1dSRodney W. Grimes */ 367f708ef1bSPoul-Henning Kamp static void 36826f9a767SRodney W. Grimes vm_object_terminate(object) 369df8bae1dSRodney W. Grimes register vm_object_t object; 370df8bae1dSRodney W. Grimes { 3713af76890SPoul-Henning Kamp register vm_page_t p; 37226f9a767SRodney W. Grimes int s; 373df8bae1dSRodney W. Grimes 374df8bae1dSRodney W. Grimes /* 375f6b04d2bSDavid Greenman * wait for the pageout daemon to be done with the object 376df8bae1dSRodney W. Grimes */ 377b18bfc3dSJohn Dyson s = splvm(); 378df8bae1dSRodney W. Grimes while (object->paging_in_progress) { 379c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 38024a1cce3SDavid Greenman tsleep(object, PVM, "objtrm", 0); 381df8bae1dSRodney W. Grimes } 3820d94caffSDavid Greenman splx(s); 383df8bae1dSRodney W. Grimes 38426f9a767SRodney W. Grimes if (object->paging_in_progress != 0) 38526f9a767SRodney W. Grimes panic("vm_object_deallocate: pageout in progress"); 38626f9a767SRodney W. Grimes 38726f9a767SRodney W. Grimes /* 3880d94caffSDavid Greenman * Clean and free the pages, as appropriate. All references to the 3890d94caffSDavid Greenman * object are gone, so we don't need to lock it. 39026f9a767SRodney W. Grimes */ 39124a1cce3SDavid Greenman if (object->type == OBJT_VNODE) { 39224a1cce3SDavid Greenman struct vnode *vp = object->handle; 393996c772fSJohn Dyson struct proc *p = curproc; /* XXX */ 3946476c0d2SJohn Dyson int waslocked; 395f6b04d2bSDavid Greenman 3966476c0d2SJohn Dyson waslocked = VOP_ISLOCKED(vp); 3976476c0d2SJohn Dyson if (!waslocked) 398996c772fSJohn Dyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 39924a1cce3SDavid Greenman vm_object_page_clean(object, 0, 0, TRUE, FALSE); 400f6b04d2bSDavid Greenman vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); 4016476c0d2SJohn Dyson if (!waslocked) 402996c772fSJohn Dyson VOP_UNLOCK(vp, 0, p); 403df8bae1dSRodney W. Grimes } 404996c772fSJohn Dyson 4050d94caffSDavid Greenman /* 4060d94caffSDavid Greenman * Now free the pages. For internal objects, this also removes them 4070d94caffSDavid Greenman * from paging queues. 408df8bae1dSRodney W. Grimes */ 409b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&object->memq)) != NULL) { 410a2f4a846SJohn Dyson if (p->busy || (p->flags & PG_BUSY)) 411be6d5bfaSDavid Greenman printf("vm_object_terminate: freeing busy page\n"); 4120d94caffSDavid Greenman PAGE_WAKEUP(p); 413df8bae1dSRodney W. Grimes vm_page_free(p); 414df8bae1dSRodney W. Grimes cnt.v_pfree++; 415df8bae1dSRodney W. Grimes } 416df8bae1dSRodney W. Grimes 417df8bae1dSRodney W. Grimes /* 418df8bae1dSRodney W. Grimes * Let the pager know object is dead. 419df8bae1dSRodney W. Grimes */ 42024a1cce3SDavid Greenman vm_pager_deallocate(object); 421df8bae1dSRodney W. Grimes 422996c772fSJohn Dyson simple_lock(&vm_object_list_lock); 423df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, object, object_list); 424df8bae1dSRodney W. Grimes vm_object_count--; 425996c772fSJohn Dyson simple_unlock(&vm_object_list_lock); 426df8bae1dSRodney W. Grimes 4270426122fSDavid Greenman wakeup(object); 4280426122fSDavid Greenman 429df8bae1dSRodney W. Grimes /* 430df8bae1dSRodney W. Grimes * Free the space for the object. 431df8bae1dSRodney W. Grimes */ 432df8bae1dSRodney W. Grimes free((caddr_t) object, M_VMOBJ); 433df8bae1dSRodney W. Grimes } 434df8bae1dSRodney W. Grimes 435df8bae1dSRodney W. Grimes /* 436df8bae1dSRodney W. Grimes * vm_object_page_clean 437df8bae1dSRodney W. Grimes * 438df8bae1dSRodney W. Grimes * Clean all dirty pages in the specified range of object. 43926f9a767SRodney W. Grimes * Leaves page on whatever queue it is currently on. 44026f9a767SRodney W. Grimes * 44126f9a767SRodney W. Grimes * Odd semantics: if start == end, we clean everything. 44226f9a767SRodney W. Grimes * 44326f9a767SRodney W. Grimes * The object must be locked. 44426f9a767SRodney W. Grimes */ 445f6b04d2bSDavid Greenman 446f6b04d2bSDavid Greenman void 44724a1cce3SDavid Greenman vm_object_page_clean(object, start, end, syncio, lockflag) 448f6b04d2bSDavid Greenman vm_object_t object; 449a316d390SJohn Dyson vm_pindex_t start; 450a316d390SJohn Dyson vm_pindex_t end; 451f6b04d2bSDavid Greenman boolean_t syncio; 45224a1cce3SDavid Greenman boolean_t lockflag; 453f6b04d2bSDavid Greenman { 454bd7e5f99SJohn Dyson register vm_page_t p, np, tp; 455f6b04d2bSDavid Greenman register vm_offset_t tstart, tend; 456bd7e5f99SJohn Dyson vm_pindex_t pi; 457aef922f5SJohn Dyson int s; 45824a1cce3SDavid Greenman struct vnode *vp; 459aef922f5SJohn Dyson int runlen; 460bd7e5f99SJohn Dyson int maxf; 461bd7e5f99SJohn Dyson int chkb; 462bd7e5f99SJohn Dyson int maxb; 463bd7e5f99SJohn Dyson int i; 464bd7e5f99SJohn Dyson vm_page_t maf[vm_pageout_page_count]; 465bd7e5f99SJohn Dyson vm_page_t mab[vm_pageout_page_count]; 466aef922f5SJohn Dyson vm_page_t ma[vm_pageout_page_count]; 467996c772fSJohn Dyson struct proc *pproc = curproc; /* XXX */ 468f6b04d2bSDavid Greenman 469aef922f5SJohn Dyson if (object->type != OBJT_VNODE || 470aef922f5SJohn Dyson (object->flags & OBJ_MIGHTBEDIRTY) == 0) 471f6b04d2bSDavid Greenman return; 472f6b04d2bSDavid Greenman 47324a1cce3SDavid Greenman vp = object->handle; 47424a1cce3SDavid Greenman 47524a1cce3SDavid Greenman if (lockflag) 476996c772fSJohn Dyson vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, pproc); 477aef922f5SJohn Dyson object->flags |= OBJ_CLEANING; 47824a1cce3SDavid Greenman 479f6b04d2bSDavid Greenman tstart = start; 480f6b04d2bSDavid Greenman if (end == 0) { 481f6b04d2bSDavid Greenman tend = object->size; 482f6b04d2bSDavid Greenman } else { 483f6b04d2bSDavid Greenman tend = end; 484f6b04d2bSDavid Greenman } 485a316d390SJohn Dyson if ((tstart == 0) && (tend == object->size)) { 486aef922f5SJohn Dyson object->flags &= ~(OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY); 487ec4f9fb0SDavid Greenman } 488b18bfc3dSJohn Dyson for(p = TAILQ_FIRST(&object->memq); p; p = TAILQ_NEXT(p, listq)) 489bd7e5f99SJohn Dyson p->flags |= PG_CLEANCHK; 490f6b04d2bSDavid Greenman 491bd7e5f99SJohn Dyson rescan: 492b18bfc3dSJohn Dyson for(p = TAILQ_FIRST(&object->memq); p; p = np) { 493b18bfc3dSJohn Dyson np = TAILQ_NEXT(p, listq); 494bd7e5f99SJohn Dyson 495bd7e5f99SJohn Dyson pi = p->pindex; 496bd7e5f99SJohn Dyson if (((p->flags & PG_CLEANCHK) == 0) || 497bd7e5f99SJohn Dyson (pi < tstart) || (pi >= tend) || 4985070c7f8SJohn Dyson (p->valid == 0) || 4995070c7f8SJohn Dyson ((p->queue - p->pc) == PQ_CACHE)) { 500bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 501aef922f5SJohn Dyson continue; 502f6b04d2bSDavid Greenman } 503f6b04d2bSDavid Greenman 504bd7e5f99SJohn Dyson vm_page_test_dirty(p); 505bd7e5f99SJohn Dyson if ((p->dirty & p->valid) == 0) { 506bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 507bd7e5f99SJohn Dyson continue; 508bd7e5f99SJohn Dyson } 509ec4f9fb0SDavid Greenman 510b18bfc3dSJohn Dyson s = splvm(); 511bd7e5f99SJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 512aef922f5SJohn Dyson p->flags |= PG_WANTED|PG_REFERENCED; 513aef922f5SJohn Dyson tsleep(p, PVM, "vpcwai", 0); 514f6b04d2bSDavid Greenman splx(s); 515bd7e5f99SJohn Dyson goto rescan; 516f6b04d2bSDavid Greenman } 517f6b04d2bSDavid Greenman splx(s); 518f6b04d2bSDavid Greenman 519f35329acSJohn Dyson s = splvm(); 520bd7e5f99SJohn Dyson maxf = 0; 521bd7e5f99SJohn Dyson for(i=1;i<vm_pageout_page_count;i++) { 522bd7e5f99SJohn Dyson if (tp = vm_page_lookup(object, pi + i)) { 523bd7e5f99SJohn Dyson if ((tp->flags & PG_BUSY) || 524bd7e5f99SJohn Dyson (tp->flags & PG_CLEANCHK) == 0) 525bd7e5f99SJohn Dyson break; 5265070c7f8SJohn Dyson if((tp->queue - tp->pc) == PQ_CACHE) { 5273077a9c2SJohn Dyson tp->flags &= ~PG_CLEANCHK; 5283077a9c2SJohn Dyson break; 5293077a9c2SJohn Dyson } 530bd7e5f99SJohn Dyson vm_page_test_dirty(tp); 531bd7e5f99SJohn Dyson if ((tp->dirty & tp->valid) == 0) { 532bd7e5f99SJohn Dyson tp->flags &= ~PG_CLEANCHK; 533bd7e5f99SJohn Dyson break; 534bd7e5f99SJohn Dyson } 535bd7e5f99SJohn Dyson maf[ i - 1 ] = tp; 536bd7e5f99SJohn Dyson maxf++; 537bd7e5f99SJohn Dyson continue; 538bd7e5f99SJohn Dyson } 539bd7e5f99SJohn Dyson break; 540bd7e5f99SJohn Dyson } 541aef922f5SJohn Dyson 542bd7e5f99SJohn Dyson maxb = 0; 543bd7e5f99SJohn Dyson chkb = vm_pageout_page_count - maxf; 544bd7e5f99SJohn Dyson if (chkb) { 545bd7e5f99SJohn Dyson for(i = 1; i < chkb;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 mab[ i - 1 ] = tp; 560bd7e5f99SJohn Dyson maxb++; 561bd7e5f99SJohn Dyson continue; 562bd7e5f99SJohn Dyson } 563bd7e5f99SJohn Dyson break; 564bd7e5f99SJohn Dyson } 565bd7e5f99SJohn Dyson } 566bd7e5f99SJohn Dyson 567bd7e5f99SJohn Dyson for(i=0;i<maxb;i++) { 568bd7e5f99SJohn Dyson int index = (maxb - i) - 1; 569bd7e5f99SJohn Dyson ma[index] = mab[i]; 570bd7e5f99SJohn Dyson ma[index]->flags |= PG_BUSY; 571bd7e5f99SJohn Dyson ma[index]->flags &= ~PG_CLEANCHK; 572bd7e5f99SJohn Dyson vm_page_protect(ma[index], VM_PROT_READ); 573bd7e5f99SJohn Dyson } 574bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_READ); 575aef922f5SJohn Dyson p->flags |= PG_BUSY; 576bd7e5f99SJohn Dyson p->flags &= ~PG_CLEANCHK; 577bd7e5f99SJohn Dyson ma[maxb] = p; 578bd7e5f99SJohn Dyson for(i=0;i<maxf;i++) { 579bd7e5f99SJohn Dyson int index = (maxb + i) + 1; 580bd7e5f99SJohn Dyson ma[index] = maf[i]; 581bd7e5f99SJohn Dyson ma[index]->flags |= PG_BUSY; 582bd7e5f99SJohn Dyson ma[index]->flags &= ~PG_CLEANCHK; 583bd7e5f99SJohn Dyson vm_page_protect(ma[index], VM_PROT_READ); 584f6b04d2bSDavid Greenman } 585bd7e5f99SJohn Dyson runlen = maxb + maxf + 1; 586f35329acSJohn Dyson splx(s); 587bd7e5f99SJohn Dyson vm_pageout_flush(ma, runlen, 0); 588bd7e5f99SJohn Dyson goto rescan; 589f6b04d2bSDavid Greenman } 590aef922f5SJohn Dyson 591aef922f5SJohn Dyson VOP_FSYNC(vp, NULL, syncio, curproc); 592aef922f5SJohn Dyson 59324a1cce3SDavid Greenman if (lockflag) 594996c772fSJohn Dyson VOP_UNLOCK(vp, 0, pproc); 595aef922f5SJohn Dyson object->flags &= ~OBJ_CLEANING; 596f5cf85d4SDavid Greenman return; 59726f9a767SRodney W. Grimes } 598df8bae1dSRodney W. Grimes 599f708ef1bSPoul-Henning Kamp #ifdef not_used 600f708ef1bSPoul-Henning Kamp /* XXX I cannot tell if this should be an exported symbol */ 601df8bae1dSRodney W. Grimes /* 602df8bae1dSRodney W. Grimes * vm_object_deactivate_pages 603df8bae1dSRodney W. Grimes * 604df8bae1dSRodney W. Grimes * Deactivate all pages in the specified object. (Keep its pages 605df8bae1dSRodney W. Grimes * in memory even though it is no longer referenced.) 606df8bae1dSRodney W. Grimes * 607df8bae1dSRodney W. Grimes * The object must be locked. 608df8bae1dSRodney W. Grimes */ 609f708ef1bSPoul-Henning Kamp static void 610df8bae1dSRodney W. Grimes vm_object_deactivate_pages(object) 611df8bae1dSRodney W. Grimes register vm_object_t object; 612df8bae1dSRodney W. Grimes { 613df8bae1dSRodney W. Grimes register vm_page_t p, next; 614df8bae1dSRodney W. Grimes 615b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 616b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 617df8bae1dSRodney W. Grimes vm_page_deactivate(p); 618df8bae1dSRodney W. Grimes } 619df8bae1dSRodney W. Grimes } 620f708ef1bSPoul-Henning Kamp #endif 621df8bae1dSRodney W. Grimes 622df8bae1dSRodney W. Grimes /* 623df8bae1dSRodney W. Grimes * Trim the object cache to size. 624df8bae1dSRodney W. Grimes */ 625f708ef1bSPoul-Henning Kamp static void 626df8bae1dSRodney W. Grimes vm_object_cache_trim() 627df8bae1dSRodney W. Grimes { 628df8bae1dSRodney W. Grimes register vm_object_t object; 629df8bae1dSRodney W. Grimes 6300d94caffSDavid Greenman while (vm_object_cached > vm_object_cache_max) { 631b18bfc3dSJohn Dyson object = TAILQ_FIRST(&vm_object_cached_list); 632df8bae1dSRodney W. Grimes 63324a1cce3SDavid Greenman vm_object_reference(object); 634df8bae1dSRodney W. Grimes pager_cache(object, FALSE); 635df8bae1dSRodney W. Grimes } 636df8bae1dSRodney W. Grimes } 637df8bae1dSRodney W. Grimes 63826f9a767SRodney W. Grimes 639df8bae1dSRodney W. Grimes /* 640df8bae1dSRodney W. Grimes * vm_object_pmap_copy: 641df8bae1dSRodney W. Grimes * 642df8bae1dSRodney W. Grimes * Makes all physical pages in the specified 643df8bae1dSRodney W. Grimes * object range copy-on-write. No writeable 644df8bae1dSRodney W. Grimes * references to these pages should remain. 645df8bae1dSRodney W. Grimes * 646df8bae1dSRodney W. Grimes * The object must *not* be locked. 647df8bae1dSRodney W. Grimes */ 6480d94caffSDavid Greenman void 6490d94caffSDavid Greenman vm_object_pmap_copy(object, start, end) 650df8bae1dSRodney W. Grimes register vm_object_t object; 651a316d390SJohn Dyson register vm_pindex_t start; 652a316d390SJohn Dyson register vm_pindex_t end; 653df8bae1dSRodney W. Grimes { 654df8bae1dSRodney W. Grimes register vm_page_t p; 655df8bae1dSRodney W. Grimes 656aef922f5SJohn Dyson if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) 657df8bae1dSRodney W. Grimes return; 658df8bae1dSRodney W. Grimes 659b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 660b5b40fa6SJohn Dyson p != NULL; 661b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 662f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_READ); 663df8bae1dSRodney W. Grimes } 664aef922f5SJohn Dyson 665aef922f5SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 666df8bae1dSRodney W. Grimes } 667df8bae1dSRodney W. Grimes 668df8bae1dSRodney W. Grimes /* 669df8bae1dSRodney W. Grimes * vm_object_pmap_remove: 670df8bae1dSRodney W. Grimes * 671df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 672df8bae1dSRodney W. Grimes * object range from all physical maps. 673df8bae1dSRodney W. Grimes * 674df8bae1dSRodney W. Grimes * The object must *not* be locked. 675df8bae1dSRodney W. Grimes */ 67626f9a767SRodney W. Grimes void 67726f9a767SRodney W. Grimes vm_object_pmap_remove(object, start, end) 678df8bae1dSRodney W. Grimes register vm_object_t object; 679a316d390SJohn Dyson register vm_pindex_t start; 680a316d390SJohn Dyson register vm_pindex_t end; 681df8bae1dSRodney W. Grimes { 682df8bae1dSRodney W. Grimes register vm_page_t p; 683df8bae1dSRodney W. Grimes if (object == NULL) 684df8bae1dSRodney W. Grimes return; 685b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 686b5b40fa6SJohn Dyson p != NULL; 687b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 688bd7e5f99SJohn Dyson if (p->pindex >= start && p->pindex < end) 689f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 69026f9a767SRodney W. Grimes } 6916e20a165SJohn Dyson if ((start == 0) && (object->size == end)) 6926e20a165SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 69326f9a767SRodney W. Grimes } 694df8bae1dSRodney W. Grimes 695df8bae1dSRodney W. Grimes /* 696867a482dSJohn Dyson * vm_object_madvise: 697867a482dSJohn Dyson * 698867a482dSJohn Dyson * Implements the madvise function at the object/page level. 699867a482dSJohn Dyson */ 700867a482dSJohn Dyson void 701867a482dSJohn Dyson vm_object_madvise(object, pindex, count, advise) 702867a482dSJohn Dyson vm_object_t object; 703867a482dSJohn Dyson vm_pindex_t pindex; 704867a482dSJohn Dyson int count; 705867a482dSJohn Dyson int advise; 706867a482dSJohn Dyson { 7076e20a165SJohn Dyson int s; 7086e20a165SJohn Dyson vm_pindex_t end, tpindex; 7096e20a165SJohn Dyson vm_object_t tobject; 710867a482dSJohn Dyson vm_page_t m; 711867a482dSJohn Dyson 712867a482dSJohn Dyson if (object == NULL) 713867a482dSJohn Dyson return; 714867a482dSJohn Dyson 715867a482dSJohn Dyson end = pindex + count; 716867a482dSJohn Dyson 717867a482dSJohn Dyson for (; pindex < end; pindex += 1) { 7186e20a165SJohn Dyson 7196e20a165SJohn Dyson relookup: 7206e20a165SJohn Dyson tobject = object; 7216e20a165SJohn Dyson tpindex = pindex; 7226e20a165SJohn Dyson shadowlookup: 7236e20a165SJohn Dyson m = vm_page_lookup(tobject, tpindex); 7246e20a165SJohn Dyson if (m == NULL) { 7256e20a165SJohn Dyson if (tobject->type != OBJT_DEFAULT) { 7266e20a165SJohn Dyson continue; 7276e20a165SJohn Dyson } 7286e20a165SJohn Dyson 7296e20a165SJohn Dyson tobject = tobject->backing_object; 7306e20a165SJohn Dyson if ((tobject == NULL) || (tobject->ref_count != 1)) { 7316e20a165SJohn Dyson continue; 7326e20a165SJohn Dyson } 7336e20a165SJohn Dyson tpindex += OFF_TO_IDX(tobject->backing_object_offset); 7346e20a165SJohn Dyson goto shadowlookup; 7356e20a165SJohn Dyson } 736867a482dSJohn Dyson 737867a482dSJohn Dyson /* 738867a482dSJohn Dyson * If the page is busy or not in a normal active state, 739867a482dSJohn Dyson * we skip it. Things can break if we mess with pages 740867a482dSJohn Dyson * in any of the below states. 741867a482dSJohn Dyson */ 7426e20a165SJohn Dyson if (m->hold_count || m->wire_count || 7436e20a165SJohn Dyson m->valid != VM_PAGE_BITS_ALL) { 744867a482dSJohn Dyson continue; 7456e20a165SJohn Dyson } 7466e20a165SJohn Dyson 7476e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7486e20a165SJohn Dyson s = splvm(); 7496e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7506e20a165SJohn Dyson m->flags |= PG_WANTED; 7516e20a165SJohn Dyson tsleep(m, PVM, "madvpw", 0); 7526e20a165SJohn Dyson } 7536e20a165SJohn Dyson splx(s); 7546e20a165SJohn Dyson goto relookup; 7556e20a165SJohn Dyson } 756867a482dSJohn Dyson 757867a482dSJohn Dyson if (advise == MADV_WILLNEED) { 758867a482dSJohn Dyson if (m->queue != PQ_ACTIVE) 759867a482dSJohn Dyson vm_page_activate(m); 7606e20a165SJohn Dyson } else if (advise == MADV_DONTNEED) { 761867a482dSJohn Dyson vm_page_deactivate(m); 7620a47b48bSJohn Dyson } else if (advise == MADV_FREE) { 7636e20a165SJohn Dyson pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 7646e20a165SJohn Dyson m->dirty = 0; 7650a47b48bSJohn Dyson /* 7666e20a165SJohn Dyson * Force a demand zero if attempt to read from swap. 7676e20a165SJohn Dyson * We currently don't handle vnode files correctly, 7686e20a165SJohn Dyson * and will reread stale contents unnecessarily. 7690a47b48bSJohn Dyson */ 7700a47b48bSJohn Dyson if (object->type == OBJT_SWAP) 7716e20a165SJohn Dyson swap_pager_dmzspace(tobject, m->pindex, 1); 772867a482dSJohn Dyson } 773867a482dSJohn Dyson } 774867a482dSJohn Dyson } 775867a482dSJohn Dyson 776867a482dSJohn Dyson /* 777df8bae1dSRodney W. Grimes * vm_object_shadow: 778df8bae1dSRodney W. Grimes * 779df8bae1dSRodney W. Grimes * Create a new object which is backed by the 780df8bae1dSRodney W. Grimes * specified existing object range. The source 781df8bae1dSRodney W. Grimes * object reference is deallocated. 782df8bae1dSRodney W. Grimes * 783df8bae1dSRodney W. Grimes * The new object and offset into that object 784df8bae1dSRodney W. Grimes * are returned in the source parameters. 785df8bae1dSRodney W. Grimes */ 786df8bae1dSRodney W. Grimes 78726f9a767SRodney W. Grimes void 78826f9a767SRodney W. Grimes vm_object_shadow(object, offset, length) 789df8bae1dSRodney W. Grimes vm_object_t *object; /* IN/OUT */ 790a316d390SJohn Dyson vm_ooffset_t *offset; /* IN/OUT */ 791df8bae1dSRodney W. Grimes vm_size_t length; 792df8bae1dSRodney W. Grimes { 793df8bae1dSRodney W. Grimes register vm_object_t source; 794df8bae1dSRodney W. Grimes register vm_object_t result; 795df8bae1dSRodney W. Grimes 796df8bae1dSRodney W. Grimes source = *object; 797df8bae1dSRodney W. Grimes 798df8bae1dSRodney W. Grimes /* 799df8bae1dSRodney W. Grimes * Allocate a new object with the given length 800df8bae1dSRodney W. Grimes */ 801df8bae1dSRodney W. Grimes 80224a1cce3SDavid Greenman if ((result = vm_object_allocate(OBJT_DEFAULT, length)) == NULL) 803df8bae1dSRodney W. Grimes panic("vm_object_shadow: no object for shadowing"); 804df8bae1dSRodney W. Grimes 805df8bae1dSRodney W. Grimes /* 8060d94caffSDavid Greenman * The new object shadows the source object, adding a reference to it. 8070d94caffSDavid Greenman * Our caller changes his reference to point to the new object, 8080d94caffSDavid Greenman * removing a reference to the source object. Net result: no change 8090d94caffSDavid Greenman * of reference count. 810df8bae1dSRodney W. Grimes */ 81124a1cce3SDavid Greenman result->backing_object = source; 812de5f6a77SJohn Dyson if (source) { 813de5f6a77SJohn Dyson TAILQ_INSERT_TAIL(&source->shadow_head, result, shadow_list); 814de5f6a77SJohn Dyson ++source->shadow_count; 815de5f6a77SJohn Dyson } 816df8bae1dSRodney W. Grimes 817df8bae1dSRodney W. Grimes /* 8180d94caffSDavid Greenman * Store the offset into the source object, and fix up the offset into 8190d94caffSDavid Greenman * the new object. 820df8bae1dSRodney W. Grimes */ 821df8bae1dSRodney W. Grimes 82224a1cce3SDavid Greenman result->backing_object_offset = *offset; 823df8bae1dSRodney W. Grimes 824df8bae1dSRodney W. Grimes /* 825df8bae1dSRodney W. Grimes * Return the new things 826df8bae1dSRodney W. Grimes */ 827df8bae1dSRodney W. Grimes 828df8bae1dSRodney W. Grimes *offset = 0; 829df8bae1dSRodney W. Grimes *object = result; 830df8bae1dSRodney W. Grimes } 831df8bae1dSRodney W. Grimes 832df8bae1dSRodney W. Grimes 833df8bae1dSRodney W. Grimes /* 8342fe6e4d7SDavid Greenman * this version of collapse allows the operation to occur earlier and 8352fe6e4d7SDavid Greenman * when paging_in_progress is true for an object... This is not a complete 8362fe6e4d7SDavid Greenman * operation, but should plug 99.9% of the rest of the leaks. 8372fe6e4d7SDavid Greenman */ 8382fe6e4d7SDavid Greenman static void 8392fe6e4d7SDavid Greenman vm_object_qcollapse(object) 8402fe6e4d7SDavid Greenman register vm_object_t object; 8412fe6e4d7SDavid Greenman { 8422fe6e4d7SDavid Greenman register vm_object_t backing_object; 843a316d390SJohn Dyson register vm_pindex_t backing_offset_index, paging_offset_index; 844a316d390SJohn Dyson vm_pindex_t backing_object_paging_offset_index; 845a316d390SJohn Dyson vm_pindex_t new_pindex; 8462fe6e4d7SDavid Greenman register vm_page_t p, pp; 8472fe6e4d7SDavid Greenman register vm_size_t size; 8482fe6e4d7SDavid Greenman 84924a1cce3SDavid Greenman backing_object = object->backing_object; 8502fe6e4d7SDavid Greenman if (backing_object->ref_count != 1) 8512fe6e4d7SDavid Greenman return; 8522fe6e4d7SDavid Greenman 853010cf3b9SDavid Greenman backing_object->ref_count += 2; 854010cf3b9SDavid Greenman 855a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(object->backing_object_offset); 856a316d390SJohn Dyson backing_object_paging_offset_index = OFF_TO_IDX(backing_object->paging_offset); 857a316d390SJohn Dyson paging_offset_index = OFF_TO_IDX(object->paging_offset); 8582fe6e4d7SDavid Greenman size = object->size; 859b18bfc3dSJohn Dyson p = TAILQ_FIRST(&backing_object->memq); 8602fe6e4d7SDavid Greenman while (p) { 8612fe6e4d7SDavid Greenman vm_page_t next; 8620d94caffSDavid Greenman 863b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 864bd7e5f99SJohn Dyson if ((p->flags & (PG_BUSY | PG_FICTITIOUS)) || 8655070c7f8SJohn Dyson ((p->queue - p->pc) == PQ_CACHE) || 8665070c7f8SJohn Dyson !p->valid || p->hold_count || p->wire_count || p->busy) { 8672fe6e4d7SDavid Greenman p = next; 8682fe6e4d7SDavid Greenman continue; 8692fe6e4d7SDavid Greenman } 870a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 871a316d390SJohn Dyson if (p->pindex < backing_offset_index || 872a316d390SJohn Dyson new_pindex >= size) { 87324a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 87424a1cce3SDavid Greenman swap_pager_freespace(backing_object, 875a316d390SJohn Dyson backing_object_paging_offset_index+p->pindex, 876a316d390SJohn Dyson 1); 877b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 8782fe6e4d7SDavid Greenman vm_page_free(p); 8792fe6e4d7SDavid Greenman } else { 880a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 88124a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 882a316d390SJohn Dyson paging_offset_index + new_pindex, NULL, NULL))) { 88324a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 88424a1cce3SDavid Greenman swap_pager_freespace(backing_object, 885a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 886b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 8872fe6e4d7SDavid Greenman vm_page_free(p); 8882fe6e4d7SDavid Greenman } else { 88924a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 89024a1cce3SDavid Greenman swap_pager_freespace(backing_object, 891a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 892a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 8936e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 8949b4814bbSDavid Greenman p->dirty = VM_PAGE_BITS_ALL; 8952fe6e4d7SDavid Greenman } 8962fe6e4d7SDavid Greenman } 8972fe6e4d7SDavid Greenman p = next; 8982fe6e4d7SDavid Greenman } 899010cf3b9SDavid Greenman backing_object->ref_count -= 2; 9002fe6e4d7SDavid Greenman } 9012fe6e4d7SDavid Greenman 902df8bae1dSRodney W. Grimes /* 903df8bae1dSRodney W. Grimes * vm_object_collapse: 904df8bae1dSRodney W. Grimes * 905df8bae1dSRodney W. Grimes * Collapse an object with the object backing it. 906df8bae1dSRodney W. Grimes * Pages in the backing object are moved into the 907df8bae1dSRodney W. Grimes * parent, and the backing object is deallocated. 908df8bae1dSRodney W. Grimes */ 90926f9a767SRodney W. Grimes void 91026f9a767SRodney W. Grimes vm_object_collapse(object) 91124a1cce3SDavid Greenman vm_object_t object; 912df8bae1dSRodney W. Grimes 913df8bae1dSRodney W. Grimes { 91424a1cce3SDavid Greenman vm_object_t backing_object; 915a316d390SJohn Dyson vm_ooffset_t backing_offset; 91624a1cce3SDavid Greenman vm_size_t size; 917a316d390SJohn Dyson vm_pindex_t new_pindex, backing_offset_index; 91824a1cce3SDavid Greenman vm_page_t p, pp; 919df8bae1dSRodney W. Grimes 920df8bae1dSRodney W. Grimes while (TRUE) { 921df8bae1dSRodney W. Grimes /* 922df8bae1dSRodney W. Grimes * Verify that the conditions are right for collapse: 923df8bae1dSRodney W. Grimes * 9240d94caffSDavid Greenman * The object exists and no pages in it are currently being paged 9250d94caffSDavid Greenman * out. 926df8bae1dSRodney W. Grimes */ 9272fe6e4d7SDavid Greenman if (object == NULL) 928df8bae1dSRodney W. Grimes return; 929df8bae1dSRodney W. Grimes 930b9921222SDavid Greenman /* 931b9921222SDavid Greenman * Make sure there is a backing object. 932b9921222SDavid Greenman */ 93324a1cce3SDavid Greenman if ((backing_object = object->backing_object) == NULL) 934df8bae1dSRodney W. Grimes return; 935df8bae1dSRodney W. Grimes 936f919ebdeSDavid Greenman /* 937f919ebdeSDavid Greenman * we check the backing object first, because it is most likely 93824a1cce3SDavid Greenman * not collapsable. 939f919ebdeSDavid Greenman */ 94024a1cce3SDavid Greenman if (backing_object->handle != NULL || 94124a1cce3SDavid Greenman (backing_object->type != OBJT_DEFAULT && 94224a1cce3SDavid Greenman backing_object->type != OBJT_SWAP) || 943f919ebdeSDavid Greenman (backing_object->flags & OBJ_DEAD) || 94424a1cce3SDavid Greenman object->handle != NULL || 94524a1cce3SDavid Greenman (object->type != OBJT_DEFAULT && 94624a1cce3SDavid Greenman object->type != OBJT_SWAP) || 94724a1cce3SDavid Greenman (object->flags & OBJ_DEAD)) { 9489b4814bbSDavid Greenman return; 94924a1cce3SDavid Greenman } 9509b4814bbSDavid Greenman 951f919ebdeSDavid Greenman if (object->paging_in_progress != 0 || 952f919ebdeSDavid Greenman backing_object->paging_in_progress != 0) { 953b9921222SDavid Greenman vm_object_qcollapse(object); 954df8bae1dSRodney W. Grimes return; 955df8bae1dSRodney W. Grimes } 956f919ebdeSDavid Greenman 95726f9a767SRodney W. Grimes /* 9580d94caffSDavid Greenman * We know that we can either collapse the backing object (if 9590d94caffSDavid Greenman * the parent is the only reference to it) or (perhaps) remove 9600d94caffSDavid Greenman * the parent's reference to it. 961df8bae1dSRodney W. Grimes */ 962df8bae1dSRodney W. Grimes 96324a1cce3SDavid Greenman backing_offset = object->backing_object_offset; 964a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(backing_offset); 965df8bae1dSRodney W. Grimes size = object->size; 966df8bae1dSRodney W. Grimes 967df8bae1dSRodney W. Grimes /* 9680d94caffSDavid Greenman * If there is exactly one reference to the backing object, we 9690d94caffSDavid Greenman * can collapse it into the parent. 970df8bae1dSRodney W. Grimes */ 971df8bae1dSRodney W. Grimes 972df8bae1dSRodney W. Grimes if (backing_object->ref_count == 1) { 973df8bae1dSRodney W. Grimes 974a1f6d91cSDavid Greenman backing_object->flags |= OBJ_DEAD; 975df8bae1dSRodney W. Grimes /* 976df8bae1dSRodney W. Grimes * We can collapse the backing object. 977df8bae1dSRodney W. Grimes * 9780d94caffSDavid Greenman * Move all in-memory pages from backing_object to the 9790d94caffSDavid Greenman * parent. Pages that have been paged out will be 9800d94caffSDavid Greenman * overwritten by any of the parent's pages that 9810d94caffSDavid Greenman * shadow them. 982df8bae1dSRodney W. Grimes */ 983df8bae1dSRodney W. Grimes 984b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&backing_object->memq)) != 0) { 98526f9a767SRodney W. Grimes 986a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 987df8bae1dSRodney W. Grimes 988df8bae1dSRodney W. Grimes /* 9890d94caffSDavid Greenman * If the parent has a page here, or if this 9900d94caffSDavid Greenman * page falls outside the parent, dispose of 9910d94caffSDavid Greenman * it. 992df8bae1dSRodney W. Grimes * 993df8bae1dSRodney W. Grimes * Otherwise, move it as planned. 994df8bae1dSRodney W. Grimes */ 995df8bae1dSRodney W. Grimes 996a316d390SJohn Dyson if (p->pindex < backing_offset_index || 997a316d390SJohn Dyson new_pindex >= size) { 998f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 9990d94caffSDavid Greenman PAGE_WAKEUP(p); 1000df8bae1dSRodney W. Grimes vm_page_free(p); 1001df8bae1dSRodney W. Grimes } else { 1002a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 100324a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 1004a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL))) { 1005f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 10060d94caffSDavid Greenman PAGE_WAKEUP(p); 1007df8bae1dSRodney W. Grimes vm_page_free(p); 100826f9a767SRodney W. Grimes } else { 10096e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1010a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 10116e20a165SJohn Dyson p->dirty = VM_PAGE_BITS_ALL; 1012df8bae1dSRodney W. Grimes } 1013df8bae1dSRodney W. Grimes } 1014df8bae1dSRodney W. Grimes } 1015df8bae1dSRodney W. Grimes 1016df8bae1dSRodney W. Grimes /* 1017df8bae1dSRodney W. Grimes * Move the pager from backing_object to object. 1018df8bae1dSRodney W. Grimes */ 1019df8bae1dSRodney W. Grimes 102024a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) { 102126f9a767SRodney W. Grimes backing_object->paging_in_progress++; 102224a1cce3SDavid Greenman if (object->type == OBJT_SWAP) { 102326f9a767SRodney W. Grimes object->paging_in_progress++; 102426f9a767SRodney W. Grimes /* 102526f9a767SRodney W. Grimes * copy shadow object pages into ours 10260d94caffSDavid Greenman * and destroy unneeded pages in 10270d94caffSDavid Greenman * shadow object. 102826f9a767SRodney W. Grimes */ 102926f9a767SRodney W. Grimes swap_pager_copy( 1030a316d390SJohn Dyson backing_object, 1031a316d390SJohn Dyson OFF_TO_IDX(backing_object->paging_offset), 1032a316d390SJohn Dyson object, 1033a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset), 1034a316d390SJohn Dyson OFF_TO_IDX(object->backing_object_offset)); 1035f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 103626f9a767SRodney W. Grimes } else { 103726f9a767SRodney W. Grimes object->paging_in_progress++; 103826f9a767SRodney W. Grimes /* 103924a1cce3SDavid Greenman * move the shadow backing_object's pager data to 104024a1cce3SDavid Greenman * "object" and convert "object" type to OBJT_SWAP. 104126f9a767SRodney W. Grimes */ 104224a1cce3SDavid Greenman object->type = OBJT_SWAP; 10432a4895f4SDavid Greenman object->un_pager.swp.swp_nblocks = 10442a4895f4SDavid Greenman backing_object->un_pager.swp.swp_nblocks; 10452a4895f4SDavid Greenman object->un_pager.swp.swp_allocsize = 10462a4895f4SDavid Greenman backing_object->un_pager.swp.swp_allocsize; 10472a4895f4SDavid Greenman object->un_pager.swp.swp_blocks = 10482a4895f4SDavid Greenman backing_object->un_pager.swp.swp_blocks; 10492a4895f4SDavid Greenman object->un_pager.swp.swp_poip = /* XXX */ 10502a4895f4SDavid Greenman backing_object->un_pager.swp.swp_poip; 105126f9a767SRodney W. Grimes object->paging_offset = backing_object->paging_offset + backing_offset; 105224a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&swap_pager_un_object_list, object, pager_object_list); 105324a1cce3SDavid Greenman 105424a1cce3SDavid Greenman /* 105524a1cce3SDavid Greenman * Convert backing object from OBJT_SWAP to 105624a1cce3SDavid Greenman * OBJT_DEFAULT. XXX - only the TAILQ_REMOVE is 105724a1cce3SDavid Greenman * actually necessary. 105824a1cce3SDavid Greenman */ 105924a1cce3SDavid Greenman backing_object->type = OBJT_DEFAULT; 106024a1cce3SDavid Greenman TAILQ_REMOVE(&swap_pager_un_object_list, backing_object, pager_object_list); 106126f9a767SRodney W. Grimes /* 106226f9a767SRodney W. Grimes * free unnecessary blocks 106326f9a767SRodney W. Grimes */ 1064a316d390SJohn Dyson swap_pager_freespace(object, 0, 1065a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset)); 1066f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1067c0503609SDavid Greenman } 1068c0503609SDavid Greenman 1069f919ebdeSDavid Greenman vm_object_pip_wakeup(backing_object); 1070c0503609SDavid Greenman } 1071df8bae1dSRodney W. Grimes /* 1072df8bae1dSRodney W. Grimes * Object now shadows whatever backing_object did. 107324a1cce3SDavid Greenman * Note that the reference to backing_object->backing_object 1074df8bae1dSRodney W. Grimes * moves from within backing_object to within object. 1075df8bae1dSRodney W. Grimes */ 1076df8bae1dSRodney W. Grimes 107724a1cce3SDavid Greenman TAILQ_REMOVE(&object->backing_object->shadow_head, object, 107824a1cce3SDavid Greenman shadow_list); 1079de5f6a77SJohn Dyson --object->backing_object->shadow_count; 1080de5f6a77SJohn Dyson if (backing_object->backing_object) { 108124a1cce3SDavid Greenman TAILQ_REMOVE(&backing_object->backing_object->shadow_head, 108224a1cce3SDavid Greenman backing_object, shadow_list); 1083de5f6a77SJohn Dyson --backing_object->backing_object->shadow_count; 1084de5f6a77SJohn Dyson } 108524a1cce3SDavid Greenman object->backing_object = backing_object->backing_object; 1086de5f6a77SJohn Dyson if (object->backing_object) { 108724a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&object->backing_object->shadow_head, 108824a1cce3SDavid Greenman object, shadow_list); 1089de5f6a77SJohn Dyson ++object->backing_object->shadow_count; 1090de5f6a77SJohn Dyson } 10912fe6e4d7SDavid Greenman 109224a1cce3SDavid Greenman object->backing_object_offset += backing_object->backing_object_offset; 1093df8bae1dSRodney W. Grimes /* 1094df8bae1dSRodney W. Grimes * Discard backing_object. 1095df8bae1dSRodney W. Grimes * 10960d94caffSDavid Greenman * Since the backing object has no pages, no pager left, 10970d94caffSDavid Greenman * and no object references within it, all that is 10980d94caffSDavid Greenman * necessary is to dispose of it. 1099df8bae1dSRodney W. Grimes */ 1100df8bae1dSRodney W. Grimes 1101df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, backing_object, 1102df8bae1dSRodney W. Grimes object_list); 1103df8bae1dSRodney W. Grimes vm_object_count--; 1104df8bae1dSRodney W. Grimes 1105df8bae1dSRodney W. Grimes free((caddr_t) backing_object, M_VMOBJ); 1106df8bae1dSRodney W. Grimes 1107df8bae1dSRodney W. Grimes object_collapses++; 11080d94caffSDavid Greenman } else { 1109df8bae1dSRodney W. Grimes /* 1110df8bae1dSRodney W. Grimes * If all of the pages in the backing object are 11110d94caffSDavid Greenman * shadowed by the parent object, the parent object no 11120d94caffSDavid Greenman * longer has to shadow the backing object; it can 11130d94caffSDavid Greenman * shadow the next one in the chain. 1114df8bae1dSRodney W. Grimes * 11150d94caffSDavid Greenman * The backing object must not be paged out - we'd have 11160d94caffSDavid Greenman * to check all of the paged-out pages, as well. 1117df8bae1dSRodney W. Grimes */ 1118df8bae1dSRodney W. Grimes 111924a1cce3SDavid Greenman if (backing_object->type != OBJT_DEFAULT) { 1120df8bae1dSRodney W. Grimes return; 1121df8bae1dSRodney W. Grimes } 1122df8bae1dSRodney W. Grimes /* 11230d94caffSDavid Greenman * Should have a check for a 'small' number of pages 11240d94caffSDavid Greenman * here. 1125df8bae1dSRodney W. Grimes */ 1126df8bae1dSRodney W. Grimes 1127b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&backing_object->memq); p; p = TAILQ_NEXT(p, listq)) { 1128a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 1129df8bae1dSRodney W. Grimes 1130df8bae1dSRodney W. Grimes /* 11310d94caffSDavid Greenman * If the parent has a page here, or if this 11320d94caffSDavid Greenman * page falls outside the parent, keep going. 1133df8bae1dSRodney W. Grimes * 11340d94caffSDavid Greenman * Otherwise, the backing_object must be left in 11350d94caffSDavid Greenman * the chain. 1136df8bae1dSRodney W. Grimes */ 1137df8bae1dSRodney W. Grimes 1138a316d390SJohn Dyson if (p->pindex >= backing_offset_index && 1139a316d390SJohn Dyson new_pindex <= size) { 114024a1cce3SDavid Greenman 1141a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 114224a1cce3SDavid Greenman 114324a1cce3SDavid Greenman if ((pp == NULL || pp->valid == 0) && 1144a316d390SJohn Dyson !vm_pager_has_page(object, OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL)) { 1145df8bae1dSRodney W. Grimes /* 11460d94caffSDavid Greenman * Page still needed. Can't go any 11470d94caffSDavid Greenman * further. 1148df8bae1dSRodney W. Grimes */ 1149df8bae1dSRodney W. Grimes return; 1150df8bae1dSRodney W. Grimes } 1151df8bae1dSRodney W. Grimes } 115224a1cce3SDavid Greenman } 1153df8bae1dSRodney W. Grimes 1154df8bae1dSRodney W. Grimes /* 11550d94caffSDavid Greenman * Make the parent shadow the next object in the 11560d94caffSDavid Greenman * chain. Deallocating backing_object will not remove 11570d94caffSDavid Greenman * it, since its reference count is at least 2. 1158df8bae1dSRodney W. Grimes */ 1159df8bae1dSRodney W. Grimes 116024a1cce3SDavid Greenman TAILQ_REMOVE(&object->backing_object->shadow_head, 116124a1cce3SDavid Greenman object, shadow_list); 1162de5f6a77SJohn Dyson --object->backing_object->shadow_count; 116324a1cce3SDavid Greenman vm_object_reference(object->backing_object = backing_object->backing_object); 1164de5f6a77SJohn Dyson if (object->backing_object) { 116524a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&object->backing_object->shadow_head, 116624a1cce3SDavid Greenman object, shadow_list); 1167de5f6a77SJohn Dyson ++object->backing_object->shadow_count; 1168de5f6a77SJohn Dyson } 116924a1cce3SDavid Greenman object->backing_object_offset += backing_object->backing_object_offset; 1170df8bae1dSRodney W. Grimes 1171df8bae1dSRodney W. Grimes /* 11720d94caffSDavid Greenman * Drop the reference count on backing_object. Since 11730d94caffSDavid Greenman * its ref_count was at least 2, it will not vanish; 11740d94caffSDavid Greenman * so we don't need to call vm_object_deallocate. 1175df8bae1dSRodney W. Grimes */ 117626f9a767SRodney W. Grimes if (backing_object->ref_count == 1) 117726f9a767SRodney W. Grimes printf("should have called obj deallocate\n"); 1178df8bae1dSRodney W. Grimes backing_object->ref_count--; 1179df8bae1dSRodney W. Grimes 1180df8bae1dSRodney W. Grimes object_bypasses++; 1181df8bae1dSRodney W. Grimes 1182df8bae1dSRodney W. Grimes } 1183df8bae1dSRodney W. Grimes 1184df8bae1dSRodney W. Grimes /* 1185df8bae1dSRodney W. Grimes * Try again with this object's new backing object. 1186df8bae1dSRodney W. Grimes */ 1187df8bae1dSRodney W. Grimes } 1188df8bae1dSRodney W. Grimes } 1189df8bae1dSRodney W. Grimes 1190df8bae1dSRodney W. Grimes /* 1191df8bae1dSRodney W. Grimes * vm_object_page_remove: [internal] 1192df8bae1dSRodney W. Grimes * 1193df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 1194df8bae1dSRodney W. Grimes * object range from the object's list of pages. 1195df8bae1dSRodney W. Grimes * 1196df8bae1dSRodney W. Grimes * The object must be locked. 1197df8bae1dSRodney W. Grimes */ 119826f9a767SRodney W. Grimes void 11997c1f6cedSDavid Greenman vm_object_page_remove(object, start, end, clean_only) 1200df8bae1dSRodney W. Grimes register vm_object_t object; 1201a316d390SJohn Dyson register vm_pindex_t start; 1202a316d390SJohn Dyson register vm_pindex_t end; 12037c1f6cedSDavid Greenman boolean_t clean_only; 1204df8bae1dSRodney W. Grimes { 1205df8bae1dSRodney W. Grimes register vm_page_t p, next; 1206a316d390SJohn Dyson unsigned int size; 120726f9a767SRodney W. Grimes int s; 1208df8bae1dSRodney W. Grimes 1209df8bae1dSRodney W. Grimes if (object == NULL) 1210df8bae1dSRodney W. Grimes return; 1211df8bae1dSRodney W. Grimes 12122fe6e4d7SDavid Greenman object->paging_in_progress++; 121326f9a767SRodney W. Grimes again: 121426f9a767SRodney W. Grimes size = end - start; 1215a316d390SJohn Dyson if (size > 4 || size >= object->size / 4) { 1216b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 1217b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 12180891ef4cSJohn Dyson if ((start <= p->pindex) && (p->pindex < end)) { 1219bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1220bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1221bd7e5f99SJohn Dyson p->valid = 0; 12220d94caffSDavid Greenman continue; 12230d94caffSDavid Greenman } 12240891ef4cSJohn Dyson 1225b18bfc3dSJohn Dyson /* 1226b18bfc3dSJohn Dyson * The busy flags are only cleared at 1227b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1228b18bfc3dSJohn Dyson */ 1229b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1230b18bfc3dSJohn Dyson s = splvm(); 12310d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 123226f9a767SRodney W. Grimes p->flags |= PG_WANTED; 123324a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1234a481f200SDavid Greenman splx(s); 123526f9a767SRodney W. Grimes goto again; 123626f9a767SRodney W. Grimes } 1237a481f200SDavid Greenman splx(s); 1238b18bfc3dSJohn Dyson } 12390891ef4cSJohn Dyson 12407c1f6cedSDavid Greenman if (clean_only) { 12417c1f6cedSDavid Greenman vm_page_test_dirty(p); 12427c1f6cedSDavid Greenman if (p->valid & p->dirty) 12437c1f6cedSDavid Greenman continue; 12447c1f6cedSDavid Greenman } 1245f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 12460d94caffSDavid Greenman PAGE_WAKEUP(p); 1247df8bae1dSRodney W. Grimes vm_page_free(p); 124826f9a767SRodney W. Grimes } 124926f9a767SRodney W. Grimes } 125026f9a767SRodney W. Grimes } else { 125126f9a767SRodney W. Grimes while (size > 0) { 1252bd7e5f99SJohn Dyson if ((p = vm_page_lookup(object, start)) != 0) { 1253bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1254bd7e5f99SJohn Dyson p->valid = 0; 1255bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1256bd7e5f99SJohn Dyson start += 1; 1257bd7e5f99SJohn Dyson size -= 1; 1258bd7e5f99SJohn Dyson continue; 12590d94caffSDavid Greenman } 1260b18bfc3dSJohn Dyson /* 1261b18bfc3dSJohn Dyson * The busy flags are only cleared at 1262b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1263b18bfc3dSJohn Dyson */ 1264b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1265b18bfc3dSJohn Dyson s = splvm(); 12660d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 126726f9a767SRodney W. Grimes p->flags |= PG_WANTED; 126824a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1269a481f200SDavid Greenman splx(s); 127026f9a767SRodney W. Grimes goto again; 127126f9a767SRodney W. Grimes } 1272a481f200SDavid Greenman splx(s); 1273b18bfc3dSJohn Dyson } 12747c1f6cedSDavid Greenman if (clean_only) { 12757c1f6cedSDavid Greenman vm_page_test_dirty(p); 1276bd7e5f99SJohn Dyson if (p->valid & p->dirty) { 1277bd7e5f99SJohn Dyson start += 1; 1278bd7e5f99SJohn Dyson size -= 1; 12797c1f6cedSDavid Greenman continue; 12807c1f6cedSDavid Greenman } 1281bd7e5f99SJohn Dyson } 1282f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 12830d94caffSDavid Greenman PAGE_WAKEUP(p); 128426f9a767SRodney W. Grimes vm_page_free(p); 128526f9a767SRodney W. Grimes } 1286a316d390SJohn Dyson start += 1; 1287a316d390SJohn Dyson size -= 1; 1288df8bae1dSRodney W. Grimes } 1289df8bae1dSRodney W. Grimes } 1290f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1291c0503609SDavid Greenman } 1292df8bae1dSRodney W. Grimes 1293df8bae1dSRodney W. Grimes /* 1294df8bae1dSRodney W. Grimes * Routine: vm_object_coalesce 1295df8bae1dSRodney W. Grimes * Function: Coalesces two objects backing up adjoining 1296df8bae1dSRodney W. Grimes * regions of memory into a single object. 1297df8bae1dSRodney W. Grimes * 1298df8bae1dSRodney W. Grimes * returns TRUE if objects were combined. 1299df8bae1dSRodney W. Grimes * 1300df8bae1dSRodney W. Grimes * NOTE: Only works at the moment if the second object is NULL - 1301df8bae1dSRodney W. Grimes * if it's not, which object do we lock first? 1302df8bae1dSRodney W. Grimes * 1303df8bae1dSRodney W. Grimes * Parameters: 1304df8bae1dSRodney W. Grimes * prev_object First object to coalesce 1305df8bae1dSRodney W. Grimes * prev_offset Offset into prev_object 1306df8bae1dSRodney W. Grimes * next_object Second object into coalesce 1307df8bae1dSRodney W. Grimes * next_offset Offset into next_object 1308df8bae1dSRodney W. Grimes * 1309df8bae1dSRodney W. Grimes * prev_size Size of reference to prev_object 1310df8bae1dSRodney W. Grimes * next_size Size of reference to next_object 1311df8bae1dSRodney W. Grimes * 1312df8bae1dSRodney W. Grimes * Conditions: 1313df8bae1dSRodney W. Grimes * The object must *not* be locked. 1314df8bae1dSRodney W. Grimes */ 13150d94caffSDavid Greenman boolean_t 1316a316d390SJohn Dyson vm_object_coalesce(prev_object, prev_pindex, prev_size, next_size) 1317df8bae1dSRodney W. Grimes register vm_object_t prev_object; 1318a316d390SJohn Dyson vm_pindex_t prev_pindex; 1319df8bae1dSRodney W. Grimes vm_size_t prev_size, next_size; 1320df8bae1dSRodney W. Grimes { 1321df8bae1dSRodney W. Grimes vm_size_t newsize; 1322df8bae1dSRodney W. Grimes 1323df8bae1dSRodney W. Grimes if (prev_object == NULL) { 1324df8bae1dSRodney W. Grimes return (TRUE); 1325df8bae1dSRodney W. Grimes } 1326df8bae1dSRodney W. Grimes 132730dcfc09SJohn Dyson if (prev_object->type != OBJT_DEFAULT) { 132830dcfc09SJohn Dyson return (FALSE); 132930dcfc09SJohn Dyson } 133030dcfc09SJohn Dyson 1331df8bae1dSRodney W. Grimes /* 1332df8bae1dSRodney W. Grimes * Try to collapse the object first 1333df8bae1dSRodney W. Grimes */ 1334df8bae1dSRodney W. Grimes vm_object_collapse(prev_object); 1335df8bae1dSRodney W. Grimes 1336df8bae1dSRodney W. Grimes /* 13370d94caffSDavid Greenman * Can't coalesce if: . more than one reference . paged out . shadows 13380d94caffSDavid Greenman * another object . has a copy elsewhere (any of which mean that the 13390d94caffSDavid Greenman * pages not mapped to prev_entry may be in use anyway) 1340df8bae1dSRodney W. Grimes */ 1341df8bae1dSRodney W. Grimes 13428cc7e047SJohn Dyson if (prev_object->backing_object != NULL) { 1343df8bae1dSRodney W. Grimes return (FALSE); 1344df8bae1dSRodney W. Grimes } 1345a316d390SJohn Dyson 1346a316d390SJohn Dyson prev_size >>= PAGE_SHIFT; 1347a316d390SJohn Dyson next_size >>= PAGE_SHIFT; 13488cc7e047SJohn Dyson 13498cc7e047SJohn Dyson if ((prev_object->ref_count > 1) && 13508cc7e047SJohn Dyson (prev_object->size != prev_pindex + prev_size)) { 13518cc7e047SJohn Dyson return (FALSE); 13528cc7e047SJohn Dyson } 13538cc7e047SJohn Dyson 1354df8bae1dSRodney W. Grimes /* 13550d94caffSDavid Greenman * Remove any pages that may still be in the object from a previous 13560d94caffSDavid Greenman * deallocation. 1357df8bae1dSRodney W. Grimes */ 1358df8bae1dSRodney W. Grimes 1359df8bae1dSRodney W. Grimes vm_object_page_remove(prev_object, 1360a316d390SJohn Dyson prev_pindex + prev_size, 1361a316d390SJohn Dyson prev_pindex + prev_size + next_size, FALSE); 1362df8bae1dSRodney W. Grimes 1363df8bae1dSRodney W. Grimes /* 1364df8bae1dSRodney W. Grimes * Extend the object if necessary. 1365df8bae1dSRodney W. Grimes */ 1366a316d390SJohn Dyson newsize = prev_pindex + prev_size + next_size; 1367df8bae1dSRodney W. Grimes if (newsize > prev_object->size) 1368df8bae1dSRodney W. Grimes prev_object->size = newsize; 1369df8bae1dSRodney W. Grimes 1370df8bae1dSRodney W. Grimes return (TRUE); 1371df8bae1dSRodney W. Grimes } 1372df8bae1dSRodney W. Grimes 1373c7c34a24SBruce Evans #include "opt_ddb.h" 1374c3cb3e12SDavid Greenman #ifdef DDB 1375c7c34a24SBruce Evans #include <sys/kernel.h> 1376c7c34a24SBruce Evans 1377c7c34a24SBruce Evans #include <machine/cons.h> 1378c7c34a24SBruce Evans 1379c7c34a24SBruce Evans #include <ddb/ddb.h> 1380c7c34a24SBruce Evans 1381c7c34a24SBruce Evans static int _vm_object_in_map __P((vm_map_t map, vm_object_t object, 1382c7c34a24SBruce Evans vm_map_entry_t entry)); 1383c7c34a24SBruce Evans static int vm_object_in_map __P((vm_object_t object)); 1384c3cb3e12SDavid Greenman 1385cac597e4SBruce Evans static int 1386a1f6d91cSDavid Greenman _vm_object_in_map(map, object, entry) 1387a1f6d91cSDavid Greenman vm_map_t map; 1388a1f6d91cSDavid Greenman vm_object_t object; 1389a1f6d91cSDavid Greenman vm_map_entry_t entry; 1390a1f6d91cSDavid Greenman { 1391a1f6d91cSDavid Greenman vm_map_t tmpm; 1392a1f6d91cSDavid Greenman vm_map_entry_t tmpe; 1393a1f6d91cSDavid Greenman vm_object_t obj; 1394a1f6d91cSDavid Greenman int entcount; 1395a1f6d91cSDavid Greenman 1396a1f6d91cSDavid Greenman if (map == 0) 1397a1f6d91cSDavid Greenman return 0; 1398a1f6d91cSDavid Greenman 1399a1f6d91cSDavid Greenman if (entry == 0) { 1400a1f6d91cSDavid Greenman tmpe = map->header.next; 1401a1f6d91cSDavid Greenman entcount = map->nentries; 1402a1f6d91cSDavid Greenman while (entcount-- && (tmpe != &map->header)) { 1403a1f6d91cSDavid Greenman if( _vm_object_in_map(map, object, tmpe)) { 1404a1f6d91cSDavid Greenman return 1; 1405a1f6d91cSDavid Greenman } 1406a1f6d91cSDavid Greenman tmpe = tmpe->next; 1407a1f6d91cSDavid Greenman } 1408afa07f7eSJohn Dyson } else if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { 1409a1f6d91cSDavid Greenman tmpm = entry->object.share_map; 1410a1f6d91cSDavid Greenman tmpe = tmpm->header.next; 1411a1f6d91cSDavid Greenman entcount = tmpm->nentries; 1412a1f6d91cSDavid Greenman while (entcount-- && tmpe != &tmpm->header) { 1413a1f6d91cSDavid Greenman if( _vm_object_in_map(tmpm, object, tmpe)) { 1414a1f6d91cSDavid Greenman return 1; 1415a1f6d91cSDavid Greenman } 1416a1f6d91cSDavid Greenman tmpe = tmpe->next; 1417a1f6d91cSDavid Greenman } 1418a1f6d91cSDavid Greenman } else if (obj = entry->object.vm_object) { 141924a1cce3SDavid Greenman for(; obj; obj=obj->backing_object) 1420a1f6d91cSDavid Greenman if( obj == object) { 1421a1f6d91cSDavid Greenman return 1; 1422a1f6d91cSDavid Greenman } 1423a1f6d91cSDavid Greenman } 1424a1f6d91cSDavid Greenman return 0; 1425a1f6d91cSDavid Greenman } 1426a1f6d91cSDavid Greenman 1427cac597e4SBruce Evans static int 1428a1f6d91cSDavid Greenman vm_object_in_map( object) 1429a1f6d91cSDavid Greenman vm_object_t object; 1430a1f6d91cSDavid Greenman { 1431a1f6d91cSDavid Greenman struct proc *p; 14321b67ec6dSJeffrey Hsu for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 1433a1f6d91cSDavid Greenman if( !p->p_vmspace /* || (p->p_flag & (P_SYSTEM|P_WEXIT)) */) 1434a1f6d91cSDavid Greenman continue; 1435a1f6d91cSDavid Greenman if( _vm_object_in_map(&p->p_vmspace->vm_map, object, 0)) 1436a1f6d91cSDavid Greenman return 1; 1437a1f6d91cSDavid Greenman } 1438a1f6d91cSDavid Greenman if( _vm_object_in_map( kernel_map, object, 0)) 1439a1f6d91cSDavid Greenman return 1; 1440a1f6d91cSDavid Greenman if( _vm_object_in_map( kmem_map, object, 0)) 1441a1f6d91cSDavid Greenman return 1; 1442a1f6d91cSDavid Greenman if( _vm_object_in_map( pager_map, object, 0)) 1443a1f6d91cSDavid Greenman return 1; 1444a1f6d91cSDavid Greenman if( _vm_object_in_map( buffer_map, object, 0)) 1445a1f6d91cSDavid Greenman return 1; 1446a1f6d91cSDavid Greenman if( _vm_object_in_map( io_map, object, 0)) 1447a1f6d91cSDavid Greenman return 1; 1448a1f6d91cSDavid Greenman if( _vm_object_in_map( phys_map, object, 0)) 1449a1f6d91cSDavid Greenman return 1; 1450a1f6d91cSDavid Greenman if( _vm_object_in_map( mb_map, object, 0)) 1451a1f6d91cSDavid Greenman return 1; 1452a1f6d91cSDavid Greenman if( _vm_object_in_map( u_map, object, 0)) 1453a1f6d91cSDavid Greenman return 1; 1454a1f6d91cSDavid Greenman return 0; 1455a1f6d91cSDavid Greenman } 1456a1f6d91cSDavid Greenman 1457c7c34a24SBruce Evans DB_SHOW_COMMAND(vmochk, vm_object_check) 1458f708ef1bSPoul-Henning Kamp { 1459a1f6d91cSDavid Greenman vm_object_t object; 1460a1f6d91cSDavid Greenman 1461a1f6d91cSDavid Greenman /* 1462a1f6d91cSDavid Greenman * make sure that internal objs are in a map somewhere 1463a1f6d91cSDavid Greenman * and none have zero ref counts. 1464a1f6d91cSDavid Greenman */ 1465b18bfc3dSJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 1466a1f6d91cSDavid Greenman object != NULL; 1467b18bfc3dSJohn Dyson object = TAILQ_NEXT(object, object_list)) { 146824a1cce3SDavid Greenman if (object->handle == NULL && 146924a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { 1470a1f6d91cSDavid Greenman if (object->ref_count == 0) { 1471c7c34a24SBruce Evans db_printf("vmochk: internal obj has zero ref count: %d\n", 1472a1f6d91cSDavid Greenman object->size); 1473a1f6d91cSDavid Greenman } 1474a1f6d91cSDavid Greenman if (!vm_object_in_map(object)) { 1475c7c34a24SBruce Evans db_printf("vmochk: internal obj is not in a map: " 14763af76890SPoul-Henning Kamp "ref: %d, size: %d: 0x%x, backing_object: 0x%x\n", 14773af76890SPoul-Henning Kamp object->ref_count, object->size, 14783af76890SPoul-Henning Kamp object->size, object->backing_object); 1479a1f6d91cSDavid Greenman } 1480a1f6d91cSDavid Greenman } 1481a1f6d91cSDavid Greenman } 1482a1f6d91cSDavid Greenman } 1483a1f6d91cSDavid Greenman 148426f9a767SRodney W. Grimes /* 1485df8bae1dSRodney W. Grimes * vm_object_print: [ debug ] 1486df8bae1dSRodney W. Grimes */ 1487c7c34a24SBruce Evans DB_SHOW_COMMAND(object, vm_object_print_static) 1488df8bae1dSRodney W. Grimes { 1489c7c34a24SBruce Evans /* XXX convert args. */ 1490c7c34a24SBruce Evans vm_object_t object = (vm_object_t)addr; 1491c7c34a24SBruce Evans boolean_t full = have_addr; 1492c7c34a24SBruce Evans 1493df8bae1dSRodney W. Grimes register vm_page_t p; 1494df8bae1dSRodney W. Grimes 1495c7c34a24SBruce Evans /* XXX count is an (unused) arg. Avoid shadowing it. */ 1496c7c34a24SBruce Evans #define count was_count 1497c7c34a24SBruce Evans 1498df8bae1dSRodney W. Grimes register int count; 1499df8bae1dSRodney W. Grimes 1500df8bae1dSRodney W. Grimes if (object == NULL) 1501df8bae1dSRodney W. Grimes return; 1502df8bae1dSRodney W. Grimes 1503c7c34a24SBruce Evans db_iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ", 1504df8bae1dSRodney W. Grimes (int) object, (int) object->size, 1505df8bae1dSRodney W. Grimes object->resident_page_count, object->ref_count); 1506c7c34a24SBruce Evans db_printf("offset=0x%x, backing_object=(0x%x)+0x%x\n", 15072a4895f4SDavid Greenman (int) object->paging_offset, 150824a1cce3SDavid Greenman (int) object->backing_object, (int) object->backing_object_offset); 1509c7c34a24SBruce Evans db_printf("cache: next=%p, prev=%p\n", 1510b18bfc3dSJohn Dyson TAILQ_NEXT(object, cached_list), TAILQ_PREV(object, cached_list)); 1511df8bae1dSRodney W. Grimes 1512df8bae1dSRodney W. Grimes if (!full) 1513df8bae1dSRodney W. Grimes return; 1514df8bae1dSRodney W. Grimes 1515c7c34a24SBruce Evans db_indent += 2; 1516df8bae1dSRodney W. Grimes count = 0; 1517b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { 1518df8bae1dSRodney W. Grimes if (count == 0) 1519c7c34a24SBruce Evans db_iprintf("memory:="); 1520df8bae1dSRodney W. Grimes else if (count == 6) { 1521c7c34a24SBruce Evans db_printf("\n"); 1522c7c34a24SBruce Evans db_iprintf(" ..."); 1523df8bae1dSRodney W. Grimes count = 0; 1524df8bae1dSRodney W. Grimes } else 1525c7c34a24SBruce Evans db_printf(","); 1526df8bae1dSRodney W. Grimes count++; 1527df8bae1dSRodney W. Grimes 1528c7c34a24SBruce Evans db_printf("(off=0x%lx,page=0x%lx)", 1529a316d390SJohn Dyson (u_long) p->pindex, (u_long) VM_PAGE_TO_PHYS(p)); 1530df8bae1dSRodney W. Grimes } 1531df8bae1dSRodney W. Grimes if (count != 0) 1532c7c34a24SBruce Evans db_printf("\n"); 1533c7c34a24SBruce Evans db_indent -= 2; 1534df8bae1dSRodney W. Grimes } 15355070c7f8SJohn Dyson 1536c7c34a24SBruce Evans /* XXX. */ 1537c7c34a24SBruce Evans #undef count 1538c7c34a24SBruce Evans 1539c7c34a24SBruce Evans /* XXX need this non-static entry for calling from vm_map_print. */ 15405070c7f8SJohn Dyson void 1541c7c34a24SBruce Evans vm_object_print(addr, have_addr, count, modif) 1542c7c34a24SBruce Evans db_expr_t addr; 1543c7c34a24SBruce Evans boolean_t have_addr; 1544c7c34a24SBruce Evans db_expr_t count; 1545c7c34a24SBruce Evans char *modif; 1546c7c34a24SBruce Evans { 1547c7c34a24SBruce Evans vm_object_print_static(addr, have_addr, count, modif); 1548c7c34a24SBruce Evans } 1549c7c34a24SBruce Evans 1550c7c34a24SBruce Evans DB_SHOW_COMMAND(vmopag, vm_object_print_pages) 15515070c7f8SJohn Dyson { 15525070c7f8SJohn Dyson vm_object_t object; 15535070c7f8SJohn Dyson int nl = 0; 15545070c7f8SJohn Dyson int c; 15555070c7f8SJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 15565070c7f8SJohn Dyson object != NULL; 15575070c7f8SJohn Dyson object = TAILQ_NEXT(object, object_list)) { 15585070c7f8SJohn Dyson vm_pindex_t idx, fidx; 15595070c7f8SJohn Dyson vm_pindex_t osize; 15605070c7f8SJohn Dyson vm_offset_t pa = -1, padiff; 15615070c7f8SJohn Dyson int rcount; 15625070c7f8SJohn Dyson vm_page_t m; 15635070c7f8SJohn Dyson 15645070c7f8SJohn Dyson db_printf("new object: 0x%x\n", object); 15655070c7f8SJohn Dyson if ( nl > 18) { 15665070c7f8SJohn Dyson c = cngetc(); 15675070c7f8SJohn Dyson if (c != ' ') 15685070c7f8SJohn Dyson return; 15695070c7f8SJohn Dyson nl = 0; 15705070c7f8SJohn Dyson } 15715070c7f8SJohn Dyson nl++; 15725070c7f8SJohn Dyson rcount = 0; 15735070c7f8SJohn Dyson fidx = 0; 15745070c7f8SJohn Dyson osize = object->size; 15755070c7f8SJohn Dyson if (osize > 128) 15765070c7f8SJohn Dyson osize = 128; 15775070c7f8SJohn Dyson for(idx=0;idx<osize;idx++) { 15785070c7f8SJohn Dyson m = vm_page_lookup(object, idx); 15795070c7f8SJohn Dyson if (m == NULL) { 15805070c7f8SJohn Dyson if (rcount) { 15815070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", 15825070c7f8SJohn Dyson fidx, rcount, pa); 15835070c7f8SJohn Dyson if ( nl > 18) { 15845070c7f8SJohn Dyson c = cngetc(); 15855070c7f8SJohn Dyson if (c != ' ') 15865070c7f8SJohn Dyson return; 15875070c7f8SJohn Dyson nl = 0; 15885070c7f8SJohn Dyson } 15895070c7f8SJohn Dyson nl++; 15905070c7f8SJohn Dyson rcount = 0; 15915070c7f8SJohn Dyson } 15925070c7f8SJohn Dyson continue; 15935070c7f8SJohn Dyson } 15945070c7f8SJohn Dyson 15955070c7f8SJohn Dyson 15965070c7f8SJohn Dyson if (rcount && 15975070c7f8SJohn Dyson (VM_PAGE_TO_PHYS(m) == pa + rcount * PAGE_SIZE)) { 15985070c7f8SJohn Dyson ++rcount; 15995070c7f8SJohn Dyson continue; 16005070c7f8SJohn Dyson } 16015070c7f8SJohn Dyson if (rcount) { 16025070c7f8SJohn Dyson padiff = pa + rcount * PAGE_SIZE - VM_PAGE_TO_PHYS(m); 16035070c7f8SJohn Dyson padiff >>= PAGE_SHIFT; 16045070c7f8SJohn Dyson padiff &= PQ_L2_MASK; 16055070c7f8SJohn Dyson if (padiff == 0) { 16065070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m) - rcount * PAGE_SIZE; 16075070c7f8SJohn Dyson ++rcount; 16085070c7f8SJohn Dyson continue; 16095070c7f8SJohn Dyson } 16105070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)", fidx, rcount, pa); 16115070c7f8SJohn Dyson db_printf("pd(%d)\n", padiff); 16125070c7f8SJohn Dyson if ( nl > 18) { 16135070c7f8SJohn Dyson c = cngetc(); 16145070c7f8SJohn Dyson if (c != ' ') 16155070c7f8SJohn Dyson return; 16165070c7f8SJohn Dyson nl = 0; 16175070c7f8SJohn Dyson } 16185070c7f8SJohn Dyson nl++; 16195070c7f8SJohn Dyson } 16205070c7f8SJohn Dyson fidx = idx; 16215070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m); 16225070c7f8SJohn Dyson rcount = 1; 16235070c7f8SJohn Dyson } 16245070c7f8SJohn Dyson if (rcount) { 16255070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", fidx, rcount, pa); 16265070c7f8SJohn Dyson if ( nl > 18) { 16275070c7f8SJohn Dyson c = cngetc(); 16285070c7f8SJohn Dyson if (c != ' ') 16295070c7f8SJohn Dyson return; 16305070c7f8SJohn Dyson nl = 0; 16315070c7f8SJohn Dyson } 16325070c7f8SJohn Dyson nl++; 16335070c7f8SJohn Dyson } 16345070c7f8SJohn Dyson } 16355070c7f8SJohn Dyson } 1636c3cb3e12SDavid Greenman #endif /* DDB */ 1637