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 * 6495e5e988SJohn Dyson * $Id: vm_object.c,v 1.103 1997/12/29 00:24:49 dyson 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 97f6b04d2bSDavid Greenman 98df8bae1dSRodney W. Grimes /* 99df8bae1dSRodney W. Grimes * Virtual memory objects maintain the actual data 100df8bae1dSRodney W. Grimes * associated with allocated virtual memory. A given 101df8bae1dSRodney W. Grimes * page of memory exists within exactly one object. 102df8bae1dSRodney W. Grimes * 103df8bae1dSRodney W. Grimes * An object is only deallocated when all "references" 104df8bae1dSRodney W. Grimes * are given up. Only one "reference" to a given 105df8bae1dSRodney W. Grimes * region of an object should be writeable. 106df8bae1dSRodney W. Grimes * 107df8bae1dSRodney W. Grimes * Associated with each object is a list of all resident 108df8bae1dSRodney W. Grimes * memory pages belonging to that object; this list is 109df8bae1dSRodney W. Grimes * maintained by the "vm_page" module, and locked by the object's 110df8bae1dSRodney W. Grimes * lock. 111df8bae1dSRodney W. Grimes * 112df8bae1dSRodney W. Grimes * Each object also records a "pager" routine which is 113df8bae1dSRodney W. Grimes * used to retrieve (and store) pages to the proper backing 114df8bae1dSRodney W. Grimes * storage. In addition, objects may be backed by other 115df8bae1dSRodney W. Grimes * objects from which they were virtual-copied. 116df8bae1dSRodney W. Grimes * 117df8bae1dSRodney W. Grimes * The only items within the object structure which are 118df8bae1dSRodney W. Grimes * modified after time of creation are: 119df8bae1dSRodney W. Grimes * reference count locked by object's lock 120df8bae1dSRodney W. Grimes * pager routine locked by object's lock 121df8bae1dSRodney W. Grimes * 122df8bae1dSRodney W. Grimes */ 123df8bae1dSRodney W. Grimes 12428f8db14SBruce Evans struct object_q vm_object_list; 125996c772fSJohn Dyson struct simplelock vm_object_list_lock; 1264de628deSBruce Evans static long vm_object_count; /* count of all objects */ 12728f8db14SBruce Evans vm_object_t kernel_object; 12828f8db14SBruce Evans vm_object_t kmem_object; 129f708ef1bSPoul-Henning Kamp static struct vm_object kernel_object_store; 130f708ef1bSPoul-Henning Kamp static struct vm_object kmem_object_store; 131aef922f5SJohn Dyson extern int vm_pageout_page_count; 132df8bae1dSRodney W. Grimes 133f708ef1bSPoul-Henning Kamp static long object_collapses; 134f708ef1bSPoul-Henning Kamp static long object_bypasses; 1355070c7f8SJohn Dyson static int next_index; 13699448ed1SJohn Dyson static vm_zone_t obj_zone; 13799448ed1SJohn Dyson static struct vm_zone obj_zone_store; 13899448ed1SJohn Dyson #define VM_OBJECTS_INIT 256 13999448ed1SJohn Dyson struct vm_object vm_objects_init[VM_OBJECTS_INIT]; 140df8bae1dSRodney W. Grimes 1413075778bSJohn Dyson void 14224a1cce3SDavid Greenman _vm_object_allocate(type, size, object) 14324a1cce3SDavid Greenman objtype_t type; 144df8bae1dSRodney W. Grimes vm_size_t size; 145df8bae1dSRodney W. Grimes register vm_object_t object; 146df8bae1dSRodney W. Grimes { 14799448ed1SJohn Dyson int incr; 148df8bae1dSRodney W. Grimes TAILQ_INIT(&object->memq); 14924a1cce3SDavid Greenman TAILQ_INIT(&object->shadow_head); 150a1f6d91cSDavid Greenman 15124a1cce3SDavid Greenman object->type = type; 152df8bae1dSRodney W. Grimes object->size = size; 153a1f6d91cSDavid Greenman object->ref_count = 1; 15424a1cce3SDavid Greenman object->flags = 0; 155867a482dSJohn Dyson object->behavior = OBJ_NORMAL; 156df8bae1dSRodney W. Grimes object->paging_in_progress = 0; 157a1f6d91cSDavid Greenman object->resident_page_count = 0; 158de5f6a77SJohn Dyson object->shadow_count = 0; 1595070c7f8SJohn Dyson object->pg_color = next_index; 16099448ed1SJohn Dyson if ( size > (PQ_L2_SIZE / 3 + PQ_PRIME1)) 16199448ed1SJohn Dyson incr = PQ_L2_SIZE / 3 + PQ_PRIME1; 16299448ed1SJohn Dyson else 16399448ed1SJohn Dyson incr = size; 16499448ed1SJohn Dyson next_index = (next_index + incr) & PQ_L2_MASK; 16524a1cce3SDavid Greenman object->handle = NULL; 166a316d390SJohn Dyson object->paging_offset = (vm_ooffset_t) 0; 16724a1cce3SDavid Greenman object->backing_object = NULL; 168a316d390SJohn Dyson object->backing_object_offset = (vm_ooffset_t) 0; 169a2f4a846SJohn Dyson object->page_hint = NULL; 170a1f6d91cSDavid Greenman 171a1f6d91cSDavid Greenman object->last_read = 0; 172df8bae1dSRodney W. Grimes 173df8bae1dSRodney W. Grimes TAILQ_INSERT_TAIL(&vm_object_list, object, object_list); 174df8bae1dSRodney W. Grimes vm_object_count++; 175df8bae1dSRodney W. Grimes } 176df8bae1dSRodney W. Grimes 177df8bae1dSRodney W. Grimes /* 17826f9a767SRodney W. Grimes * vm_object_init: 17926f9a767SRodney W. Grimes * 18026f9a767SRodney W. Grimes * Initialize the VM objects module. 18126f9a767SRodney W. Grimes */ 18226f9a767SRodney W. Grimes void 183a316d390SJohn Dyson vm_object_init() 18426f9a767SRodney W. Grimes { 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 18926f9a767SRodney W. Grimes kernel_object = &kernel_object_store; 190a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 19126f9a767SRodney W. Grimes kernel_object); 19226f9a767SRodney W. Grimes 19326f9a767SRodney W. Grimes kmem_object = &kmem_object_store; 194a316d390SJohn Dyson _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS), 19526f9a767SRodney W. Grimes kmem_object); 19699448ed1SJohn Dyson 19799448ed1SJohn Dyson obj_zone = &obj_zone_store; 19899448ed1SJohn Dyson zbootinit(obj_zone, "VM OBJECT", sizeof (struct vm_object), 19999448ed1SJohn Dyson vm_objects_init, VM_OBJECTS_INIT); 20099448ed1SJohn Dyson } 20199448ed1SJohn Dyson 20299448ed1SJohn Dyson void 20399448ed1SJohn Dyson vm_object_init2() { 2040a80f406SJohn Dyson zinitna(obj_zone, NULL, NULL, 0, 0, 0, 1); 20526f9a767SRodney W. Grimes } 20626f9a767SRodney W. Grimes 20726f9a767SRodney W. Grimes /* 20826f9a767SRodney W. Grimes * vm_object_allocate: 20926f9a767SRodney W. Grimes * 21026f9a767SRodney W. Grimes * Returns a new object with the given size. 21126f9a767SRodney W. Grimes */ 21226f9a767SRodney W. Grimes 21326f9a767SRodney W. Grimes vm_object_t 21424a1cce3SDavid Greenman vm_object_allocate(type, size) 21524a1cce3SDavid Greenman objtype_t type; 21626f9a767SRodney W. Grimes vm_size_t size; 21726f9a767SRodney W. Grimes { 21826f9a767SRodney W. Grimes register vm_object_t result; 21999448ed1SJohn Dyson result = (vm_object_t) zalloc(obj_zone); 22067bf6868SJohn Dyson 22124a1cce3SDavid Greenman _vm_object_allocate(type, size, result); 22226f9a767SRodney W. Grimes 22326f9a767SRodney W. Grimes return (result); 22426f9a767SRodney W. Grimes } 22526f9a767SRodney W. Grimes 22626f9a767SRodney W. Grimes 22726f9a767SRodney W. Grimes /* 228df8bae1dSRodney W. Grimes * vm_object_reference: 229df8bae1dSRodney W. Grimes * 230df8bae1dSRodney W. Grimes * Gets another reference to the given object. 231df8bae1dSRodney W. Grimes */ 2326476c0d2SJohn Dyson void 23326f9a767SRodney W. Grimes vm_object_reference(object) 234df8bae1dSRodney W. Grimes register vm_object_t object; 235df8bae1dSRodney W. Grimes { 236df8bae1dSRodney W. Grimes if (object == NULL) 237df8bae1dSRodney W. Grimes return; 23895e5e988SJohn Dyson 23995e5e988SJohn Dyson #if defined(DIAGNOSTIC) 24095e5e988SJohn Dyson if (object->flags & OBJ_DEAD) 24195e5e988SJohn Dyson panic("vm_object_reference: attempting to reference dead obj"); 24295e5e988SJohn Dyson #endif 24395e5e988SJohn Dyson 244df8bae1dSRodney W. Grimes object->ref_count++; 24595e5e988SJohn Dyson if (object->type == OBJT_VNODE) 24695e5e988SJohn Dyson vget((struct vnode *) object->handle, LK_NOOBJ, curproc); 24795e5e988SJohn Dyson } 24895e5e988SJohn Dyson 24995e5e988SJohn Dyson inline void 25095e5e988SJohn Dyson vm_object_vndeallocate(object) 25195e5e988SJohn Dyson vm_object_t object; 25295e5e988SJohn Dyson { 25395e5e988SJohn Dyson struct vnode *vp = (struct vnode *) object->handle; 25495e5e988SJohn Dyson #if defined(DIAGNOSTIC) 25595e5e988SJohn Dyson if (object->type != OBJT_VNODE) 25695e5e988SJohn Dyson panic("vm_object_vndeallocate: not a vnode object"); 25795e5e988SJohn Dyson if (vp == NULL) 25895e5e988SJohn Dyson panic("vm_object_vndeallocate: missing vp"); 25995e5e988SJohn Dyson if (object->ref_count == 0) { 26095e5e988SJohn Dyson vprint("vm_object_vndeallocate", vp); 26195e5e988SJohn Dyson panic("vm_object_vndeallocate: bad object reference count"); 26295e5e988SJohn Dyson } 26395e5e988SJohn Dyson #endif 26495e5e988SJohn Dyson 26595e5e988SJohn Dyson object->ref_count--; 26695e5e988SJohn Dyson if (object->type == OBJT_VNODE) { 26795e5e988SJohn Dyson vrele(vp); 2682be70f79SJohn Dyson } 269df8bae1dSRodney W. Grimes } 270df8bae1dSRodney W. Grimes 271df8bae1dSRodney W. Grimes /* 272df8bae1dSRodney W. Grimes * vm_object_deallocate: 273df8bae1dSRodney W. Grimes * 274df8bae1dSRodney W. Grimes * Release a reference to the specified object, 275df8bae1dSRodney W. Grimes * gained either through a vm_object_allocate 276df8bae1dSRodney W. Grimes * or a vm_object_reference call. When all references 277df8bae1dSRodney W. Grimes * are gone, storage associated with this object 278df8bae1dSRodney W. Grimes * may be relinquished. 279df8bae1dSRodney W. Grimes * 280df8bae1dSRodney W. Grimes * No object may be locked. 281df8bae1dSRodney W. Grimes */ 28226f9a767SRodney W. Grimes void 28326f9a767SRodney W. Grimes vm_object_deallocate(object) 28426f9a767SRodney W. Grimes vm_object_t object; 285df8bae1dSRodney W. Grimes { 28695e5e988SJohn Dyson int s; 287df8bae1dSRodney W. Grimes vm_object_t temp; 288df8bae1dSRodney W. Grimes 289df8bae1dSRodney W. Grimes while (object != NULL) { 290df8bae1dSRodney W. Grimes 29195e5e988SJohn Dyson if (object->type == OBJT_VNODE) { 29295e5e988SJohn Dyson vm_object_vndeallocate(object); 29395e5e988SJohn Dyson return; 29495e5e988SJohn Dyson } 29595e5e988SJohn Dyson 2962be70f79SJohn Dyson if (object->ref_count == 0) { 297ba8da839SDavid Greenman panic("vm_object_deallocate: object deallocated too many times"); 2982be70f79SJohn Dyson } else if (object->ref_count > 2) { 2992be70f79SJohn Dyson object->ref_count--; 3002be70f79SJohn Dyson return; 3012be70f79SJohn Dyson } 3022be70f79SJohn Dyson 3032be70f79SJohn Dyson /* 3042be70f79SJohn Dyson * Here on ref_count of one or two, which are special cases for 3052be70f79SJohn Dyson * objects. 3062be70f79SJohn Dyson */ 30795e5e988SJohn Dyson if ((object->ref_count == 2) && (object->shadow_count == 1)) { 3082be70f79SJohn Dyson 309be6d5bfaSDavid Greenman object->ref_count--; 3102be70f79SJohn Dyson if ((object->handle == NULL) && 31124a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || 31224a1cce3SDavid Greenman object->type == OBJT_SWAP)) { 313a1f6d91cSDavid Greenman vm_object_t robject; 31495e5e988SJohn Dyson 315b18bfc3dSJohn Dyson robject = TAILQ_FIRST(&object->shadow_head); 31695e5e988SJohn Dyson #if defined(DIAGNOSTIC) 31795e5e988SJohn Dyson if (robject == NULL) 31895e5e988SJohn Dyson panic("vm_object_deallocate: ref_count: %d," 31995e5e988SJohn Dyson " shadow_count: %d", 32095e5e988SJohn Dyson object->ref_count, object->shadow_count); 32195e5e988SJohn Dyson #endif 32295e5e988SJohn Dyson if ((robject->handle == NULL) && 32324a1cce3SDavid Greenman (robject->type == OBJT_DEFAULT || 32424a1cce3SDavid Greenman robject->type == OBJT_SWAP)) { 325a1f6d91cSDavid Greenman 32695e5e988SJohn Dyson robject->ref_count++; 32795e5e988SJohn Dyson 32895e5e988SJohn Dyson retry: 329b18bfc3dSJohn Dyson s = splvm(); 33095e5e988SJohn Dyson if (robject->paging_in_progress) { 331c0503609SDavid Greenman robject->flags |= OBJ_PIPWNT; 332a1f6d91cSDavid Greenman tsleep(robject, PVM, "objde1", 0); 33395e5e988SJohn Dyson goto retry; 3340d94caffSDavid Greenman } 335a1f6d91cSDavid Greenman 33695e5e988SJohn Dyson if (object->paging_in_progress) { 337c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 338a1f6d91cSDavid Greenman tsleep(object, PVM, "objde2", 0); 33995e5e988SJohn Dyson goto retry; 340a1f6d91cSDavid Greenman } 341a1f6d91cSDavid Greenman splx(s); 342a1f6d91cSDavid Greenman 34395e5e988SJohn Dyson if( robject->ref_count == 1) { 34495e5e988SJohn Dyson robject->ref_count--; 345ba8da839SDavid Greenman object = robject; 34695e5e988SJohn Dyson goto doterm; 34795e5e988SJohn Dyson } 34895e5e988SJohn Dyson 34995e5e988SJohn Dyson object = robject; 35095e5e988SJohn Dyson vm_object_collapse(object); 351ba8da839SDavid Greenman continue; 352a1f6d91cSDavid Greenman } 35395e5e988SJohn Dyson } 35495e5e988SJohn Dyson 355a1f6d91cSDavid Greenman return; 356df8bae1dSRodney W. Grimes 35795e5e988SJohn Dyson } else { 3581efb74fbSJohn Dyson object->ref_count--; 35995e5e988SJohn Dyson if (object->ref_count != 0) 36095e5e988SJohn Dyson return; 36195e5e988SJohn Dyson } 36295e5e988SJohn Dyson 36395e5e988SJohn Dyson doterm: 3641efb74fbSJohn Dyson 36524a1cce3SDavid Greenman temp = object->backing_object; 366de5f6a77SJohn Dyson if (temp) { 36724a1cce3SDavid Greenman TAILQ_REMOVE(&temp->shadow_head, object, shadow_list); 36895e5e988SJohn Dyson temp->shadow_count--; 369de5f6a77SJohn Dyson } 370df8bae1dSRodney W. Grimes vm_object_terminate(object); 371df8bae1dSRodney W. Grimes /* unlocks and deallocates object */ 372df8bae1dSRodney W. Grimes object = temp; 373df8bae1dSRodney W. Grimes } 374df8bae1dSRodney W. Grimes } 375df8bae1dSRodney W. Grimes 376df8bae1dSRodney W. Grimes /* 377df8bae1dSRodney W. Grimes * vm_object_terminate actually destroys the specified object, freeing 378df8bae1dSRodney W. Grimes * up all previously used resources. 379df8bae1dSRodney W. Grimes * 380df8bae1dSRodney W. Grimes * The object must be locked. 381df8bae1dSRodney W. Grimes */ 38295e5e988SJohn Dyson void 38326f9a767SRodney W. Grimes vm_object_terminate(object) 384df8bae1dSRodney W. Grimes register vm_object_t object; 385df8bae1dSRodney W. Grimes { 3863af76890SPoul-Henning Kamp register vm_page_t p; 38726f9a767SRodney W. Grimes int s; 388df8bae1dSRodney W. Grimes 38995e5e988SJohn Dyson /* 39095e5e988SJohn Dyson * Make sure no one uses us. 39195e5e988SJohn Dyson */ 39295e5e988SJohn Dyson object->flags |= OBJ_DEAD; 3933c631446SJohn Dyson 394df8bae1dSRodney W. Grimes /* 395f6b04d2bSDavid Greenman * wait for the pageout daemon to be done with the object 396df8bae1dSRodney W. Grimes */ 397b18bfc3dSJohn Dyson s = splvm(); 398df8bae1dSRodney W. Grimes while (object->paging_in_progress) { 399c0503609SDavid Greenman object->flags |= OBJ_PIPWNT; 40024a1cce3SDavid Greenman tsleep(object, PVM, "objtrm", 0); 401df8bae1dSRodney W. Grimes } 4020d94caffSDavid Greenman splx(s); 403df8bae1dSRodney W. Grimes 40495e5e988SJohn Dyson #if defined(DIAGNOSTIC) 40526f9a767SRodney W. Grimes if (object->paging_in_progress != 0) 40626f9a767SRodney W. Grimes panic("vm_object_deallocate: pageout in progress"); 40795e5e988SJohn Dyson #endif 40826f9a767SRodney W. Grimes 40926f9a767SRodney W. Grimes /* 4100d94caffSDavid Greenman * Clean and free the pages, as appropriate. All references to the 4110d94caffSDavid Greenman * object are gone, so we don't need to lock it. 41226f9a767SRodney W. Grimes */ 41324a1cce3SDavid Greenman if (object->type == OBJT_VNODE) { 41495e5e988SJohn Dyson struct vnode *vp; 41595e5e988SJohn Dyson 41695e5e988SJohn Dyson /* 41795e5e988SJohn Dyson * Freeze optimized copies. 41895e5e988SJohn Dyson */ 41995e5e988SJohn Dyson vm_freeze_copyopts(object, 0, object->size); 42095e5e988SJohn Dyson 42195e5e988SJohn Dyson /* 42295e5e988SJohn Dyson * Clean pages and flush buffers. 42395e5e988SJohn Dyson */ 4242be70f79SJohn Dyson vm_object_page_clean(object, 0, 0, TRUE); 42595e5e988SJohn Dyson 42695e5e988SJohn Dyson vp = (struct vnode *) object->handle; 427f6b04d2bSDavid Greenman vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0); 42895e5e988SJohn Dyson 42995e5e988SJohn Dyson } else { 430996c772fSJohn Dyson 4310d94caffSDavid Greenman /* 4320d94caffSDavid Greenman * Now free the pages. For internal objects, this also removes them 4330d94caffSDavid Greenman * from paging queues. 434df8bae1dSRodney W. Grimes */ 435b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&object->memq)) != NULL) { 436a2f4a846SJohn Dyson if (p->busy || (p->flags & PG_BUSY)) 437be6d5bfaSDavid Greenman printf("vm_object_terminate: freeing busy page\n"); 4380d94caffSDavid Greenman PAGE_WAKEUP(p); 439df8bae1dSRodney W. Grimes vm_page_free(p); 440df8bae1dSRodney W. Grimes cnt.v_pfree++; 441df8bae1dSRodney W. Grimes } 44295e5e988SJohn Dyson } 443df8bae1dSRodney W. Grimes 444df8bae1dSRodney W. Grimes /* 445df8bae1dSRodney W. Grimes * Let the pager know object is dead. 446df8bae1dSRodney W. Grimes */ 44724a1cce3SDavid Greenman vm_pager_deallocate(object); 448df8bae1dSRodney W. Grimes 449996c772fSJohn Dyson simple_lock(&vm_object_list_lock); 450df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, object, object_list); 451df8bae1dSRodney W. Grimes vm_object_count--; 452996c772fSJohn Dyson simple_unlock(&vm_object_list_lock); 453df8bae1dSRodney W. Grimes 4540426122fSDavid Greenman wakeup(object); 4550426122fSDavid Greenman 456df8bae1dSRodney W. Grimes /* 457df8bae1dSRodney W. Grimes * Free the space for the object. 458df8bae1dSRodney W. Grimes */ 45999448ed1SJohn Dyson zfree(obj_zone, object); 460df8bae1dSRodney W. Grimes } 461df8bae1dSRodney W. Grimes 462df8bae1dSRodney W. Grimes /* 463df8bae1dSRodney W. Grimes * vm_object_page_clean 464df8bae1dSRodney W. Grimes * 465df8bae1dSRodney W. Grimes * Clean all dirty pages in the specified range of object. 46626f9a767SRodney W. Grimes * Leaves page on whatever queue it is currently on. 46726f9a767SRodney W. Grimes * 46826f9a767SRodney W. Grimes * Odd semantics: if start == end, we clean everything. 46926f9a767SRodney W. Grimes * 47026f9a767SRodney W. Grimes * The object must be locked. 47126f9a767SRodney W. Grimes */ 472f6b04d2bSDavid Greenman 473f6b04d2bSDavid Greenman void 4742be70f79SJohn Dyson vm_object_page_clean(object, start, end, syncio) 475f6b04d2bSDavid Greenman vm_object_t object; 476a316d390SJohn Dyson vm_pindex_t start; 477a316d390SJohn Dyson vm_pindex_t end; 478f6b04d2bSDavid Greenman boolean_t syncio; 479f6b04d2bSDavid Greenman { 480bd7e5f99SJohn Dyson register vm_page_t p, np, tp; 481f6b04d2bSDavid Greenman register vm_offset_t tstart, tend; 482bd7e5f99SJohn Dyson vm_pindex_t pi; 483aef922f5SJohn Dyson int s; 48424a1cce3SDavid Greenman struct vnode *vp; 485aef922f5SJohn Dyson int runlen; 486bd7e5f99SJohn Dyson int maxf; 487bd7e5f99SJohn Dyson int chkb; 488bd7e5f99SJohn Dyson int maxb; 489bd7e5f99SJohn Dyson int i; 490bd7e5f99SJohn Dyson vm_page_t maf[vm_pageout_page_count]; 491bd7e5f99SJohn Dyson vm_page_t mab[vm_pageout_page_count]; 492aef922f5SJohn Dyson vm_page_t ma[vm_pageout_page_count]; 493996c772fSJohn Dyson struct proc *pproc = curproc; /* XXX */ 494f6b04d2bSDavid Greenman 495aef922f5SJohn Dyson if (object->type != OBJT_VNODE || 496aef922f5SJohn Dyson (object->flags & OBJ_MIGHTBEDIRTY) == 0) 497f6b04d2bSDavid Greenman return; 498f6b04d2bSDavid Greenman 49924a1cce3SDavid Greenman vp = object->handle; 50024a1cce3SDavid Greenman 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 617aef922f5SJohn Dyson object->flags &= ~OBJ_CLEANING; 618f5cf85d4SDavid Greenman return; 61926f9a767SRodney W. Grimes } 620df8bae1dSRodney W. Grimes 621f708ef1bSPoul-Henning Kamp #ifdef not_used 622f708ef1bSPoul-Henning Kamp /* XXX I cannot tell if this should be an exported symbol */ 623df8bae1dSRodney W. Grimes /* 624df8bae1dSRodney W. Grimes * vm_object_deactivate_pages 625df8bae1dSRodney W. Grimes * 626df8bae1dSRodney W. Grimes * Deactivate all pages in the specified object. (Keep its pages 627df8bae1dSRodney W. Grimes * in memory even though it is no longer referenced.) 628df8bae1dSRodney W. Grimes * 629df8bae1dSRodney W. Grimes * The object must be locked. 630df8bae1dSRodney W. Grimes */ 631f708ef1bSPoul-Henning Kamp static void 632df8bae1dSRodney W. Grimes vm_object_deactivate_pages(object) 633df8bae1dSRodney W. Grimes register vm_object_t object; 634df8bae1dSRodney W. Grimes { 635df8bae1dSRodney W. Grimes register vm_page_t p, next; 636df8bae1dSRodney W. Grimes 637b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 638b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 639df8bae1dSRodney W. Grimes vm_page_deactivate(p); 640df8bae1dSRodney W. Grimes } 641df8bae1dSRodney W. Grimes } 642f708ef1bSPoul-Henning Kamp #endif 643df8bae1dSRodney W. Grimes 644df8bae1dSRodney W. Grimes /* 645df8bae1dSRodney W. Grimes * vm_object_pmap_copy: 646df8bae1dSRodney W. Grimes * 647df8bae1dSRodney W. Grimes * Makes all physical pages in the specified 648df8bae1dSRodney W. Grimes * object range copy-on-write. No writeable 649df8bae1dSRodney W. Grimes * references to these pages should remain. 650df8bae1dSRodney W. Grimes * 651df8bae1dSRodney W. Grimes * The object must *not* be locked. 652df8bae1dSRodney W. Grimes */ 6530d94caffSDavid Greenman void 6540d94caffSDavid Greenman vm_object_pmap_copy(object, start, end) 655df8bae1dSRodney W. Grimes register vm_object_t object; 656a316d390SJohn Dyson register vm_pindex_t start; 657a316d390SJohn Dyson register vm_pindex_t end; 658df8bae1dSRodney W. Grimes { 659df8bae1dSRodney W. Grimes register vm_page_t p; 660df8bae1dSRodney W. Grimes 661aef922f5SJohn Dyson if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) 662df8bae1dSRodney W. Grimes return; 663df8bae1dSRodney W. Grimes 664b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 665b5b40fa6SJohn Dyson p != NULL; 666b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 667f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_READ); 668df8bae1dSRodney W. Grimes } 669aef922f5SJohn Dyson 670aef922f5SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 671df8bae1dSRodney W. Grimes } 672df8bae1dSRodney W. Grimes 673df8bae1dSRodney W. Grimes /* 6741efb74fbSJohn Dyson * Same as vm_object_pmap_copy_1, except range checking really 6751efb74fbSJohn Dyson * works, and is meant for small sections of an object. 6761efb74fbSJohn Dyson */ 6771efb74fbSJohn Dyson void 6781efb74fbSJohn Dyson vm_object_pmap_copy_1(object, start, end) 6791efb74fbSJohn Dyson register vm_object_t object; 6801efb74fbSJohn Dyson register vm_pindex_t start; 6811efb74fbSJohn Dyson register vm_pindex_t end; 6821efb74fbSJohn Dyson { 6831efb74fbSJohn Dyson vm_pindex_t idx; 6841efb74fbSJohn Dyson register vm_page_t p; 6851efb74fbSJohn Dyson 6861efb74fbSJohn Dyson if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0) 6871efb74fbSJohn Dyson return; 6881efb74fbSJohn Dyson 6891efb74fbSJohn Dyson for (idx = start; idx < end; idx++) { 6901efb74fbSJohn Dyson p = vm_page_lookup(object, idx); 6911efb74fbSJohn Dyson if (p == NULL) 6921efb74fbSJohn Dyson continue; 6931efb74fbSJohn Dyson vm_page_protect(p, VM_PROT_READ); 6941efb74fbSJohn Dyson } 6951efb74fbSJohn Dyson } 6961efb74fbSJohn Dyson 6971efb74fbSJohn Dyson /* 698df8bae1dSRodney W. Grimes * vm_object_pmap_remove: 699df8bae1dSRodney W. Grimes * 700df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 701df8bae1dSRodney W. Grimes * object range from all physical maps. 702df8bae1dSRodney W. Grimes * 703df8bae1dSRodney W. Grimes * The object must *not* be locked. 704df8bae1dSRodney W. Grimes */ 70526f9a767SRodney W. Grimes void 70626f9a767SRodney W. Grimes vm_object_pmap_remove(object, start, end) 707df8bae1dSRodney W. Grimes register vm_object_t object; 708a316d390SJohn Dyson register vm_pindex_t start; 709a316d390SJohn Dyson register vm_pindex_t end; 710df8bae1dSRodney W. Grimes { 711df8bae1dSRodney W. Grimes register vm_page_t p; 712df8bae1dSRodney W. Grimes if (object == NULL) 713df8bae1dSRodney W. Grimes return; 714b5b40fa6SJohn Dyson for (p = TAILQ_FIRST(&object->memq); 715b5b40fa6SJohn Dyson p != NULL; 716b5b40fa6SJohn Dyson p = TAILQ_NEXT(p, listq)) { 717bd7e5f99SJohn Dyson if (p->pindex >= start && p->pindex < end) 718f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 71926f9a767SRodney W. Grimes } 7206e20a165SJohn Dyson if ((start == 0) && (object->size == end)) 7216e20a165SJohn Dyson object->flags &= ~OBJ_WRITEABLE; 72226f9a767SRodney W. Grimes } 723df8bae1dSRodney W. Grimes 724df8bae1dSRodney W. Grimes /* 725867a482dSJohn Dyson * vm_object_madvise: 726867a482dSJohn Dyson * 727867a482dSJohn Dyson * Implements the madvise function at the object/page level. 728867a482dSJohn Dyson */ 729867a482dSJohn Dyson void 730867a482dSJohn Dyson vm_object_madvise(object, pindex, count, advise) 731867a482dSJohn Dyson vm_object_t object; 732867a482dSJohn Dyson vm_pindex_t pindex; 733867a482dSJohn Dyson int count; 734867a482dSJohn Dyson int advise; 735867a482dSJohn Dyson { 7366e20a165SJohn Dyson int s; 7376e20a165SJohn Dyson vm_pindex_t end, tpindex; 7386e20a165SJohn Dyson vm_object_t tobject; 739867a482dSJohn Dyson vm_page_t m; 740867a482dSJohn Dyson 741867a482dSJohn Dyson if (object == NULL) 742867a482dSJohn Dyson return; 743867a482dSJohn Dyson 744867a482dSJohn Dyson end = pindex + count; 745867a482dSJohn Dyson 746867a482dSJohn Dyson for (; pindex < end; pindex += 1) { 7476e20a165SJohn Dyson 7486e20a165SJohn Dyson relookup: 7496e20a165SJohn Dyson tobject = object; 7506e20a165SJohn Dyson tpindex = pindex; 7516e20a165SJohn Dyson shadowlookup: 7526e20a165SJohn Dyson m = vm_page_lookup(tobject, tpindex); 7536e20a165SJohn Dyson if (m == NULL) { 7546e20a165SJohn Dyson if (tobject->type != OBJT_DEFAULT) { 7556e20a165SJohn Dyson continue; 7566e20a165SJohn Dyson } 7576e20a165SJohn Dyson 7586e20a165SJohn Dyson tobject = tobject->backing_object; 7596e20a165SJohn Dyson if ((tobject == NULL) || (tobject->ref_count != 1)) { 7606e20a165SJohn Dyson continue; 7616e20a165SJohn Dyson } 7626e20a165SJohn Dyson tpindex += OFF_TO_IDX(tobject->backing_object_offset); 7636e20a165SJohn Dyson goto shadowlookup; 7646e20a165SJohn Dyson } 765867a482dSJohn Dyson 766867a482dSJohn Dyson /* 767867a482dSJohn Dyson * If the page is busy or not in a normal active state, 768867a482dSJohn Dyson * we skip it. Things can break if we mess with pages 769867a482dSJohn Dyson * in any of the below states. 770867a482dSJohn Dyson */ 7716e20a165SJohn Dyson if (m->hold_count || m->wire_count || 7726e20a165SJohn Dyson m->valid != VM_PAGE_BITS_ALL) { 773867a482dSJohn Dyson continue; 7746e20a165SJohn Dyson } 7756e20a165SJohn Dyson 7766e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7776e20a165SJohn Dyson s = splvm(); 7786e20a165SJohn Dyson if (m->busy || (m->flags & PG_BUSY)) { 7796e20a165SJohn Dyson m->flags |= PG_WANTED; 7806e20a165SJohn Dyson tsleep(m, PVM, "madvpw", 0); 7816e20a165SJohn Dyson } 7826e20a165SJohn Dyson splx(s); 7836e20a165SJohn Dyson goto relookup; 7846e20a165SJohn Dyson } 785867a482dSJohn Dyson 786867a482dSJohn Dyson if (advise == MADV_WILLNEED) { 787867a482dSJohn Dyson if (m->queue != PQ_ACTIVE) 788867a482dSJohn Dyson vm_page_activate(m); 7896e20a165SJohn Dyson } else if (advise == MADV_DONTNEED) { 790867a482dSJohn Dyson vm_page_deactivate(m); 7910a47b48bSJohn Dyson } else if (advise == MADV_FREE) { 7926e20a165SJohn Dyson pmap_clear_modify(VM_PAGE_TO_PHYS(m)); 7936e20a165SJohn Dyson m->dirty = 0; 7940a47b48bSJohn Dyson /* 7956e20a165SJohn Dyson * Force a demand zero if attempt to read from swap. 7966e20a165SJohn Dyson * We currently don't handle vnode files correctly, 7976e20a165SJohn Dyson * and will reread stale contents unnecessarily. 7980a47b48bSJohn Dyson */ 7990a47b48bSJohn Dyson if (object->type == OBJT_SWAP) 8006e20a165SJohn Dyson swap_pager_dmzspace(tobject, m->pindex, 1); 801867a482dSJohn Dyson } 802867a482dSJohn Dyson } 803867a482dSJohn Dyson } 804867a482dSJohn Dyson 805867a482dSJohn Dyson /* 806df8bae1dSRodney W. Grimes * vm_object_shadow: 807df8bae1dSRodney W. Grimes * 808df8bae1dSRodney W. Grimes * Create a new object which is backed by the 809df8bae1dSRodney W. Grimes * specified existing object range. The source 810df8bae1dSRodney W. Grimes * object reference is deallocated. 811df8bae1dSRodney W. Grimes * 812df8bae1dSRodney W. Grimes * The new object and offset into that object 813df8bae1dSRodney W. Grimes * are returned in the source parameters. 814df8bae1dSRodney W. Grimes */ 815df8bae1dSRodney W. Grimes 81626f9a767SRodney W. Grimes void 81726f9a767SRodney W. Grimes vm_object_shadow(object, offset, length) 818df8bae1dSRodney W. Grimes vm_object_t *object; /* IN/OUT */ 819a316d390SJohn Dyson vm_ooffset_t *offset; /* IN/OUT */ 820df8bae1dSRodney W. Grimes vm_size_t length; 821df8bae1dSRodney W. Grimes { 822df8bae1dSRodney W. Grimes register vm_object_t source; 823df8bae1dSRodney W. Grimes register vm_object_t result; 824df8bae1dSRodney W. Grimes 825df8bae1dSRodney W. Grimes source = *object; 826df8bae1dSRodney W. Grimes 827df8bae1dSRodney W. Grimes /* 828df8bae1dSRodney W. Grimes * Allocate a new object with the given length 829df8bae1dSRodney W. Grimes */ 830df8bae1dSRodney W. Grimes 83124a1cce3SDavid Greenman if ((result = vm_object_allocate(OBJT_DEFAULT, length)) == NULL) 832df8bae1dSRodney W. Grimes panic("vm_object_shadow: no object for shadowing"); 833df8bae1dSRodney W. Grimes 834df8bae1dSRodney W. Grimes /* 8350d94caffSDavid Greenman * The new object shadows the source object, adding a reference to it. 8360d94caffSDavid Greenman * Our caller changes his reference to point to the new object, 8370d94caffSDavid Greenman * removing a reference to the source object. Net result: no change 8380d94caffSDavid Greenman * of reference count. 839df8bae1dSRodney W. Grimes */ 84024a1cce3SDavid Greenman result->backing_object = source; 841de5f6a77SJohn Dyson if (source) { 842de5f6a77SJohn Dyson TAILQ_INSERT_TAIL(&source->shadow_head, result, shadow_list); 843de5f6a77SJohn Dyson ++source->shadow_count; 844de5f6a77SJohn Dyson } 845df8bae1dSRodney W. Grimes 846df8bae1dSRodney W. Grimes /* 8470d94caffSDavid Greenman * Store the offset into the source object, and fix up the offset into 8480d94caffSDavid Greenman * the new object. 849df8bae1dSRodney W. Grimes */ 850df8bae1dSRodney W. Grimes 85124a1cce3SDavid Greenman result->backing_object_offset = *offset; 852df8bae1dSRodney W. Grimes 853df8bae1dSRodney W. Grimes /* 854df8bae1dSRodney W. Grimes * Return the new things 855df8bae1dSRodney W. Grimes */ 856df8bae1dSRodney W. Grimes 857df8bae1dSRodney W. Grimes *offset = 0; 858df8bae1dSRodney W. Grimes *object = result; 859df8bae1dSRodney W. Grimes } 860df8bae1dSRodney W. Grimes 861df8bae1dSRodney W. Grimes 862df8bae1dSRodney W. Grimes /* 8632fe6e4d7SDavid Greenman * this version of collapse allows the operation to occur earlier and 8642fe6e4d7SDavid Greenman * when paging_in_progress is true for an object... This is not a complete 8652fe6e4d7SDavid Greenman * operation, but should plug 99.9% of the rest of the leaks. 8662fe6e4d7SDavid Greenman */ 8672fe6e4d7SDavid Greenman static void 8682fe6e4d7SDavid Greenman vm_object_qcollapse(object) 8692fe6e4d7SDavid Greenman register vm_object_t object; 8702fe6e4d7SDavid Greenman { 8712fe6e4d7SDavid Greenman register vm_object_t backing_object; 872a316d390SJohn Dyson register vm_pindex_t backing_offset_index, paging_offset_index; 873a316d390SJohn Dyson vm_pindex_t backing_object_paging_offset_index; 874a316d390SJohn Dyson vm_pindex_t new_pindex; 8752fe6e4d7SDavid Greenman register vm_page_t p, pp; 8762fe6e4d7SDavid Greenman register vm_size_t size; 8772fe6e4d7SDavid Greenman 87824a1cce3SDavid Greenman backing_object = object->backing_object; 8792fe6e4d7SDavid Greenman if (backing_object->ref_count != 1) 8802fe6e4d7SDavid Greenman return; 8812fe6e4d7SDavid Greenman 882010cf3b9SDavid Greenman backing_object->ref_count += 2; 883010cf3b9SDavid Greenman 884a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(object->backing_object_offset); 885a316d390SJohn Dyson backing_object_paging_offset_index = OFF_TO_IDX(backing_object->paging_offset); 886a316d390SJohn Dyson paging_offset_index = OFF_TO_IDX(object->paging_offset); 8872fe6e4d7SDavid Greenman size = object->size; 888b18bfc3dSJohn Dyson p = TAILQ_FIRST(&backing_object->memq); 8892fe6e4d7SDavid Greenman while (p) { 8902fe6e4d7SDavid Greenman vm_page_t next; 8910d94caffSDavid Greenman 892b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 893bd7e5f99SJohn Dyson if ((p->flags & (PG_BUSY | PG_FICTITIOUS)) || 8945070c7f8SJohn Dyson ((p->queue - p->pc) == PQ_CACHE) || 8955070c7f8SJohn Dyson !p->valid || p->hold_count || p->wire_count || p->busy) { 8962fe6e4d7SDavid Greenman p = next; 8972fe6e4d7SDavid Greenman continue; 8982fe6e4d7SDavid Greenman } 899a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 900a316d390SJohn Dyson if (p->pindex < backing_offset_index || 901a316d390SJohn Dyson new_pindex >= size) { 90224a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 90324a1cce3SDavid Greenman swap_pager_freespace(backing_object, 904a316d390SJohn Dyson backing_object_paging_offset_index+p->pindex, 905a316d390SJohn Dyson 1); 906b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9072fe6e4d7SDavid Greenman vm_page_free(p); 9082fe6e4d7SDavid Greenman } else { 909a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 91024a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 911a316d390SJohn Dyson paging_offset_index + new_pindex, NULL, NULL))) { 91224a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 91324a1cce3SDavid Greenman swap_pager_freespace(backing_object, 914a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 915b18bfc3dSJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9162fe6e4d7SDavid Greenman vm_page_free(p); 9172fe6e4d7SDavid Greenman } else { 91824a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) 91924a1cce3SDavid Greenman swap_pager_freespace(backing_object, 920a316d390SJohn Dyson backing_object_paging_offset_index + p->pindex, 1); 921a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 9226e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 9239b4814bbSDavid Greenman p->dirty = VM_PAGE_BITS_ALL; 9242fe6e4d7SDavid Greenman } 9252fe6e4d7SDavid Greenman } 9262fe6e4d7SDavid Greenman p = next; 9272fe6e4d7SDavid Greenman } 928010cf3b9SDavid Greenman backing_object->ref_count -= 2; 9292fe6e4d7SDavid Greenman } 9302fe6e4d7SDavid Greenman 931df8bae1dSRodney W. Grimes /* 932df8bae1dSRodney W. Grimes * vm_object_collapse: 933df8bae1dSRodney W. Grimes * 934df8bae1dSRodney W. Grimes * Collapse an object with the object backing it. 935df8bae1dSRodney W. Grimes * Pages in the backing object are moved into the 936df8bae1dSRodney W. Grimes * parent, and the backing object is deallocated. 937df8bae1dSRodney W. Grimes */ 93826f9a767SRodney W. Grimes void 93926f9a767SRodney W. Grimes vm_object_collapse(object) 94024a1cce3SDavid Greenman vm_object_t object; 941df8bae1dSRodney W. Grimes 942df8bae1dSRodney W. Grimes { 94324a1cce3SDavid Greenman vm_object_t backing_object; 944a316d390SJohn Dyson vm_ooffset_t backing_offset; 94524a1cce3SDavid Greenman vm_size_t size; 946a316d390SJohn Dyson vm_pindex_t new_pindex, backing_offset_index; 94724a1cce3SDavid Greenman vm_page_t p, pp; 948df8bae1dSRodney W. Grimes 949df8bae1dSRodney W. Grimes while (TRUE) { 950df8bae1dSRodney W. Grimes /* 951df8bae1dSRodney W. Grimes * Verify that the conditions are right for collapse: 952df8bae1dSRodney W. Grimes * 9530d94caffSDavid Greenman * The object exists and no pages in it are currently being paged 9540d94caffSDavid Greenman * out. 955df8bae1dSRodney W. Grimes */ 9562fe6e4d7SDavid Greenman if (object == NULL) 957df8bae1dSRodney W. Grimes return; 958df8bae1dSRodney W. Grimes 959b9921222SDavid Greenman /* 960b9921222SDavid Greenman * Make sure there is a backing object. 961b9921222SDavid Greenman */ 96224a1cce3SDavid Greenman if ((backing_object = object->backing_object) == NULL) 963df8bae1dSRodney W. Grimes return; 964df8bae1dSRodney W. Grimes 965f919ebdeSDavid Greenman /* 966f919ebdeSDavid Greenman * we check the backing object first, because it is most likely 96724a1cce3SDavid Greenman * not collapsable. 968f919ebdeSDavid Greenman */ 96924a1cce3SDavid Greenman if (backing_object->handle != NULL || 97024a1cce3SDavid Greenman (backing_object->type != OBJT_DEFAULT && 97124a1cce3SDavid Greenman backing_object->type != OBJT_SWAP) || 972f919ebdeSDavid Greenman (backing_object->flags & OBJ_DEAD) || 97324a1cce3SDavid Greenman object->handle != NULL || 97424a1cce3SDavid Greenman (object->type != OBJT_DEFAULT && 97524a1cce3SDavid Greenman object->type != OBJT_SWAP) || 97624a1cce3SDavid Greenman (object->flags & OBJ_DEAD)) { 9779b4814bbSDavid Greenman return; 97824a1cce3SDavid Greenman } 9799b4814bbSDavid Greenman 980f919ebdeSDavid Greenman if (object->paging_in_progress != 0 || 981f919ebdeSDavid Greenman backing_object->paging_in_progress != 0) { 982b9921222SDavid Greenman vm_object_qcollapse(object); 983df8bae1dSRodney W. Grimes return; 984df8bae1dSRodney W. Grimes } 985f919ebdeSDavid Greenman 98626f9a767SRodney W. Grimes /* 9870d94caffSDavid Greenman * We know that we can either collapse the backing object (if 9880d94caffSDavid Greenman * the parent is the only reference to it) or (perhaps) remove 9890d94caffSDavid Greenman * the parent's reference to it. 990df8bae1dSRodney W. Grimes */ 991df8bae1dSRodney W. Grimes 99224a1cce3SDavid Greenman backing_offset = object->backing_object_offset; 993a316d390SJohn Dyson backing_offset_index = OFF_TO_IDX(backing_offset); 994df8bae1dSRodney W. Grimes size = object->size; 995df8bae1dSRodney W. Grimes 996df8bae1dSRodney W. Grimes /* 9970d94caffSDavid Greenman * If there is exactly one reference to the backing object, we 9980d94caffSDavid Greenman * can collapse it into the parent. 999df8bae1dSRodney W. Grimes */ 1000df8bae1dSRodney W. Grimes 1001df8bae1dSRodney W. Grimes if (backing_object->ref_count == 1) { 1002df8bae1dSRodney W. Grimes 1003a1f6d91cSDavid Greenman backing_object->flags |= OBJ_DEAD; 1004df8bae1dSRodney W. Grimes /* 1005df8bae1dSRodney W. Grimes * We can collapse the backing object. 1006df8bae1dSRodney W. Grimes * 10070d94caffSDavid Greenman * Move all in-memory pages from backing_object to the 10080d94caffSDavid Greenman * parent. Pages that have been paged out will be 10090d94caffSDavid Greenman * overwritten by any of the parent's pages that 10100d94caffSDavid Greenman * shadow them. 1011df8bae1dSRodney W. Grimes */ 1012df8bae1dSRodney W. Grimes 1013b18bfc3dSJohn Dyson while ((p = TAILQ_FIRST(&backing_object->memq)) != 0) { 101426f9a767SRodney W. Grimes 1015a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 1016df8bae1dSRodney W. Grimes 1017df8bae1dSRodney W. Grimes /* 10180d94caffSDavid Greenman * If the parent has a page here, or if this 10190d94caffSDavid Greenman * page falls outside the parent, dispose of 10200d94caffSDavid Greenman * it. 1021df8bae1dSRodney W. Grimes * 1022df8bae1dSRodney W. Grimes * Otherwise, move it as planned. 1023df8bae1dSRodney W. Grimes */ 1024df8bae1dSRodney W. Grimes 1025a316d390SJohn Dyson if (p->pindex < backing_offset_index || 1026a316d390SJohn Dyson new_pindex >= size) { 1027f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 10280d94caffSDavid Greenman PAGE_WAKEUP(p); 1029df8bae1dSRodney W. Grimes vm_page_free(p); 1030df8bae1dSRodney W. Grimes } else { 1031a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 103224a1cce3SDavid Greenman if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object, 1033a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL))) { 1034f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 10350d94caffSDavid Greenman PAGE_WAKEUP(p); 1036df8bae1dSRodney W. Grimes vm_page_free(p); 103726f9a767SRodney W. Grimes } else { 10386e20a165SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1039a316d390SJohn Dyson vm_page_rename(p, object, new_pindex); 10406e20a165SJohn Dyson p->dirty = VM_PAGE_BITS_ALL; 1041df8bae1dSRodney W. Grimes } 1042df8bae1dSRodney W. Grimes } 1043df8bae1dSRodney W. Grimes } 1044df8bae1dSRodney W. Grimes 1045df8bae1dSRodney W. Grimes /* 1046df8bae1dSRodney W. Grimes * Move the pager from backing_object to object. 1047df8bae1dSRodney W. Grimes */ 1048df8bae1dSRodney W. Grimes 104924a1cce3SDavid Greenman if (backing_object->type == OBJT_SWAP) { 105026f9a767SRodney W. Grimes backing_object->paging_in_progress++; 105124a1cce3SDavid Greenman if (object->type == OBJT_SWAP) { 105226f9a767SRodney W. Grimes object->paging_in_progress++; 105326f9a767SRodney W. Grimes /* 105426f9a767SRodney W. Grimes * copy shadow object pages into ours 10550d94caffSDavid Greenman * and destroy unneeded pages in 10560d94caffSDavid Greenman * shadow object. 105726f9a767SRodney W. Grimes */ 105826f9a767SRodney W. Grimes swap_pager_copy( 1059a316d390SJohn Dyson backing_object, 1060a316d390SJohn Dyson OFF_TO_IDX(backing_object->paging_offset), 1061a316d390SJohn Dyson object, 1062a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset), 1063a316d390SJohn Dyson OFF_TO_IDX(object->backing_object_offset)); 1064f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 106526f9a767SRodney W. Grimes } else { 106626f9a767SRodney W. Grimes object->paging_in_progress++; 106726f9a767SRodney W. Grimes /* 106824a1cce3SDavid Greenman * move the shadow backing_object's pager data to 106924a1cce3SDavid Greenman * "object" and convert "object" type to OBJT_SWAP. 107026f9a767SRodney W. Grimes */ 107124a1cce3SDavid Greenman object->type = OBJT_SWAP; 10722a4895f4SDavid Greenman object->un_pager.swp.swp_nblocks = 10732a4895f4SDavid Greenman backing_object->un_pager.swp.swp_nblocks; 10742a4895f4SDavid Greenman object->un_pager.swp.swp_allocsize = 10752a4895f4SDavid Greenman backing_object->un_pager.swp.swp_allocsize; 10762a4895f4SDavid Greenman object->un_pager.swp.swp_blocks = 10772a4895f4SDavid Greenman backing_object->un_pager.swp.swp_blocks; 10782a4895f4SDavid Greenman object->un_pager.swp.swp_poip = /* XXX */ 10792a4895f4SDavid Greenman backing_object->un_pager.swp.swp_poip; 108026f9a767SRodney W. Grimes object->paging_offset = backing_object->paging_offset + backing_offset; 108124a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&swap_pager_un_object_list, object, pager_object_list); 108224a1cce3SDavid Greenman 108324a1cce3SDavid Greenman /* 108424a1cce3SDavid Greenman * Convert backing object from OBJT_SWAP to 108524a1cce3SDavid Greenman * OBJT_DEFAULT. XXX - only the TAILQ_REMOVE is 108624a1cce3SDavid Greenman * actually necessary. 108724a1cce3SDavid Greenman */ 108824a1cce3SDavid Greenman backing_object->type = OBJT_DEFAULT; 108924a1cce3SDavid Greenman TAILQ_REMOVE(&swap_pager_un_object_list, backing_object, pager_object_list); 109026f9a767SRodney W. Grimes /* 109126f9a767SRodney W. Grimes * free unnecessary blocks 109226f9a767SRodney W. Grimes */ 1093a316d390SJohn Dyson swap_pager_freespace(object, 0, 1094a316d390SJohn Dyson OFF_TO_IDX(object->paging_offset)); 1095f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1096c0503609SDavid Greenman } 1097c0503609SDavid Greenman 1098f919ebdeSDavid Greenman vm_object_pip_wakeup(backing_object); 1099c0503609SDavid Greenman } 1100df8bae1dSRodney W. Grimes /* 1101df8bae1dSRodney W. Grimes * Object now shadows whatever backing_object did. 110224a1cce3SDavid Greenman * Note that the reference to backing_object->backing_object 1103df8bae1dSRodney W. Grimes * moves from within backing_object to within object. 1104df8bae1dSRodney W. Grimes */ 1105df8bae1dSRodney W. Grimes 110624a1cce3SDavid Greenman TAILQ_REMOVE(&object->backing_object->shadow_head, object, 110724a1cce3SDavid Greenman shadow_list); 1108de5f6a77SJohn Dyson --object->backing_object->shadow_count; 1109de5f6a77SJohn Dyson if (backing_object->backing_object) { 111024a1cce3SDavid Greenman TAILQ_REMOVE(&backing_object->backing_object->shadow_head, 111124a1cce3SDavid Greenman backing_object, shadow_list); 1112de5f6a77SJohn Dyson --backing_object->backing_object->shadow_count; 1113de5f6a77SJohn Dyson } 111424a1cce3SDavid Greenman object->backing_object = backing_object->backing_object; 1115de5f6a77SJohn Dyson if (object->backing_object) { 111624a1cce3SDavid Greenman TAILQ_INSERT_TAIL(&object->backing_object->shadow_head, 111724a1cce3SDavid Greenman object, shadow_list); 1118de5f6a77SJohn Dyson ++object->backing_object->shadow_count; 1119de5f6a77SJohn Dyson } 11202fe6e4d7SDavid Greenman 112124a1cce3SDavid Greenman object->backing_object_offset += backing_object->backing_object_offset; 1122df8bae1dSRodney W. Grimes /* 1123df8bae1dSRodney W. Grimes * Discard backing_object. 1124df8bae1dSRodney W. Grimes * 11250d94caffSDavid Greenman * Since the backing object has no pages, no pager left, 11260d94caffSDavid Greenman * and no object references within it, all that is 11270d94caffSDavid Greenman * necessary is to dispose of it. 1128df8bae1dSRodney W. Grimes */ 1129df8bae1dSRodney W. Grimes 1130df8bae1dSRodney W. Grimes TAILQ_REMOVE(&vm_object_list, backing_object, 1131df8bae1dSRodney W. Grimes object_list); 1132df8bae1dSRodney W. Grimes vm_object_count--; 1133df8bae1dSRodney W. Grimes 113499448ed1SJohn Dyson zfree(obj_zone, backing_object); 1135df8bae1dSRodney W. Grimes 1136df8bae1dSRodney W. Grimes object_collapses++; 11370d94caffSDavid Greenman } else { 113895e5e988SJohn Dyson vm_object_t new_backing_object; 1139df8bae1dSRodney W. Grimes /* 1140df8bae1dSRodney W. Grimes * If all of the pages in the backing object are 11410d94caffSDavid Greenman * shadowed by the parent object, the parent object no 11420d94caffSDavid Greenman * longer has to shadow the backing object; it can 11430d94caffSDavid Greenman * shadow the next one in the chain. 1144df8bae1dSRodney W. Grimes * 11450d94caffSDavid Greenman * The backing object must not be paged out - we'd have 11460d94caffSDavid Greenman * to check all of the paged-out pages, as well. 1147df8bae1dSRodney W. Grimes */ 1148df8bae1dSRodney W. Grimes 114924a1cce3SDavid Greenman if (backing_object->type != OBJT_DEFAULT) { 1150df8bae1dSRodney W. Grimes return; 1151df8bae1dSRodney W. Grimes } 1152df8bae1dSRodney W. Grimes /* 11530d94caffSDavid Greenman * Should have a check for a 'small' number of pages 11540d94caffSDavid Greenman * here. 1155df8bae1dSRodney W. Grimes */ 1156df8bae1dSRodney W. Grimes 1157b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&backing_object->memq); p; p = TAILQ_NEXT(p, listq)) { 1158a316d390SJohn Dyson new_pindex = p->pindex - backing_offset_index; 1159df8bae1dSRodney W. Grimes 1160df8bae1dSRodney W. Grimes /* 11610d94caffSDavid Greenman * If the parent has a page here, or if this 11620d94caffSDavid Greenman * page falls outside the parent, keep going. 1163df8bae1dSRodney W. Grimes * 11640d94caffSDavid Greenman * Otherwise, the backing_object must be left in 11650d94caffSDavid Greenman * the chain. 1166df8bae1dSRodney W. Grimes */ 1167df8bae1dSRodney W. Grimes 1168a316d390SJohn Dyson if (p->pindex >= backing_offset_index && 1169a316d390SJohn Dyson new_pindex <= size) { 117024a1cce3SDavid Greenman 1171a316d390SJohn Dyson pp = vm_page_lookup(object, new_pindex); 117224a1cce3SDavid Greenman 117324a1cce3SDavid Greenman if ((pp == NULL || pp->valid == 0) && 1174a316d390SJohn Dyson !vm_pager_has_page(object, OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL)) { 1175df8bae1dSRodney W. Grimes /* 11760d94caffSDavid Greenman * Page still needed. Can't go any 11770d94caffSDavid Greenman * further. 1178df8bae1dSRodney W. Grimes */ 1179df8bae1dSRodney W. Grimes return; 1180df8bae1dSRodney W. Grimes } 1181df8bae1dSRodney W. Grimes } 118224a1cce3SDavid Greenman } 1183df8bae1dSRodney W. Grimes 1184df8bae1dSRodney W. Grimes /* 11850d94caffSDavid Greenman * Make the parent shadow the next object in the 11860d94caffSDavid Greenman * chain. Deallocating backing_object will not remove 11870d94caffSDavid Greenman * it, since its reference count is at least 2. 1188df8bae1dSRodney W. Grimes */ 1189df8bae1dSRodney W. Grimes 119095e5e988SJohn Dyson TAILQ_REMOVE(&backing_object->shadow_head, 119124a1cce3SDavid Greenman object, shadow_list); 119295e5e988SJohn Dyson --backing_object->shadow_count; 119395e5e988SJohn Dyson 119495e5e988SJohn Dyson new_backing_object = backing_object->backing_object; 119595e5e988SJohn Dyson if (object->backing_object = new_backing_object) { 119695e5e988SJohn Dyson vm_object_reference(new_backing_object); 119795e5e988SJohn Dyson TAILQ_INSERT_TAIL(&new_backing_object->shadow_head, 119824a1cce3SDavid Greenman object, shadow_list); 119995e5e988SJohn Dyson ++new_backing_object->shadow_count; 120095e5e988SJohn Dyson object->backing_object_offset += 120195e5e988SJohn Dyson backing_object->backing_object_offset; 1202de5f6a77SJohn Dyson } 1203df8bae1dSRodney W. Grimes 1204df8bae1dSRodney W. Grimes /* 12050d94caffSDavid Greenman * Drop the reference count on backing_object. Since 12060d94caffSDavid Greenman * its ref_count was at least 2, it will not vanish; 12070d94caffSDavid Greenman * so we don't need to call vm_object_deallocate. 1208df8bae1dSRodney W. Grimes */ 120995e5e988SJohn Dyson vm_object_deallocate(backing_object); 1210df8bae1dSRodney W. Grimes 1211df8bae1dSRodney W. Grimes object_bypasses++; 1212df8bae1dSRodney W. Grimes 1213df8bae1dSRodney W. Grimes } 1214df8bae1dSRodney W. Grimes 1215df8bae1dSRodney W. Grimes /* 1216df8bae1dSRodney W. Grimes * Try again with this object's new backing object. 1217df8bae1dSRodney W. Grimes */ 1218df8bae1dSRodney W. Grimes } 1219df8bae1dSRodney W. Grimes } 1220df8bae1dSRodney W. Grimes 1221df8bae1dSRodney W. Grimes /* 1222df8bae1dSRodney W. Grimes * vm_object_page_remove: [internal] 1223df8bae1dSRodney W. Grimes * 1224df8bae1dSRodney W. Grimes * Removes all physical pages in the specified 1225df8bae1dSRodney W. Grimes * object range from the object's list of pages. 1226df8bae1dSRodney W. Grimes * 1227df8bae1dSRodney W. Grimes * The object must be locked. 1228df8bae1dSRodney W. Grimes */ 122926f9a767SRodney W. Grimes void 12307c1f6cedSDavid Greenman vm_object_page_remove(object, start, end, clean_only) 1231df8bae1dSRodney W. Grimes register vm_object_t object; 1232a316d390SJohn Dyson register vm_pindex_t start; 1233a316d390SJohn Dyson register vm_pindex_t end; 12347c1f6cedSDavid Greenman boolean_t clean_only; 1235df8bae1dSRodney W. Grimes { 1236df8bae1dSRodney W. Grimes register vm_page_t p, next; 1237a316d390SJohn Dyson unsigned int size; 123895e5e988SJohn Dyson int s, all; 1239df8bae1dSRodney W. Grimes 1240df8bae1dSRodney W. Grimes if (object == NULL) 1241df8bae1dSRodney W. Grimes return; 1242df8bae1dSRodney W. Grimes 124395e5e988SJohn Dyson all = ((end == 0) && (start == 0)); 124495e5e988SJohn Dyson 12452fe6e4d7SDavid Greenman object->paging_in_progress++; 124626f9a767SRodney W. Grimes again: 124726f9a767SRodney W. Grimes size = end - start; 124895e5e988SJohn Dyson if (all || size > 4 || size >= object->size / 4) { 1249b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) { 1250b18bfc3dSJohn Dyson next = TAILQ_NEXT(p, listq); 125195e5e988SJohn Dyson if (all || ((start <= p->pindex) && (p->pindex < end))) { 1252bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1253bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1254bd7e5f99SJohn Dyson p->valid = 0; 12550d94caffSDavid Greenman continue; 12560d94caffSDavid Greenman } 12570891ef4cSJohn Dyson 1258b18bfc3dSJohn Dyson /* 1259b18bfc3dSJohn Dyson * The busy flags are only cleared at 1260b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1261b18bfc3dSJohn Dyson */ 1262b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1263b18bfc3dSJohn Dyson s = splvm(); 12640d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 126526f9a767SRodney W. Grimes p->flags |= PG_WANTED; 126624a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1267a481f200SDavid Greenman splx(s); 126826f9a767SRodney W. Grimes goto again; 126926f9a767SRodney W. Grimes } 1270a481f200SDavid Greenman splx(s); 1271b18bfc3dSJohn Dyson } 12720891ef4cSJohn Dyson 12737c1f6cedSDavid Greenman if (clean_only) { 12747c1f6cedSDavid Greenman vm_page_test_dirty(p); 12757c1f6cedSDavid Greenman if (p->valid & p->dirty) 12767c1f6cedSDavid Greenman continue; 12777c1f6cedSDavid Greenman } 1278f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 12790d94caffSDavid Greenman PAGE_WAKEUP(p); 1280df8bae1dSRodney W. Grimes vm_page_free(p); 128126f9a767SRodney W. Grimes } 128226f9a767SRodney W. Grimes } 128326f9a767SRodney W. Grimes } else { 128426f9a767SRodney W. Grimes while (size > 0) { 1285bd7e5f99SJohn Dyson if ((p = vm_page_lookup(object, start)) != 0) { 1286bd7e5f99SJohn Dyson if (p->wire_count != 0) { 1287bd7e5f99SJohn Dyson p->valid = 0; 1288bd7e5f99SJohn Dyson vm_page_protect(p, VM_PROT_NONE); 1289bd7e5f99SJohn Dyson start += 1; 1290bd7e5f99SJohn Dyson size -= 1; 1291bd7e5f99SJohn Dyson continue; 12920d94caffSDavid Greenman } 1293b18bfc3dSJohn Dyson /* 1294b18bfc3dSJohn Dyson * The busy flags are only cleared at 1295b18bfc3dSJohn Dyson * interrupt -- minimize the spl transitions 1296b18bfc3dSJohn Dyson */ 1297b18bfc3dSJohn Dyson if ((p->flags & PG_BUSY) || p->busy) { 1298b18bfc3dSJohn Dyson s = splvm(); 12990d94caffSDavid Greenman if ((p->flags & PG_BUSY) || p->busy) { 130026f9a767SRodney W. Grimes p->flags |= PG_WANTED; 130124a1cce3SDavid Greenman tsleep(p, PVM, "vmopar", 0); 1302a481f200SDavid Greenman splx(s); 130326f9a767SRodney W. Grimes goto again; 130426f9a767SRodney W. Grimes } 1305a481f200SDavid Greenman splx(s); 1306b18bfc3dSJohn Dyson } 13077c1f6cedSDavid Greenman if (clean_only) { 13087c1f6cedSDavid Greenman vm_page_test_dirty(p); 1309bd7e5f99SJohn Dyson if (p->valid & p->dirty) { 1310bd7e5f99SJohn Dyson start += 1; 1311bd7e5f99SJohn Dyson size -= 1; 13127c1f6cedSDavid Greenman continue; 13137c1f6cedSDavid Greenman } 1314bd7e5f99SJohn Dyson } 1315f919ebdeSDavid Greenman vm_page_protect(p, VM_PROT_NONE); 13160d94caffSDavid Greenman PAGE_WAKEUP(p); 131726f9a767SRodney W. Grimes vm_page_free(p); 131826f9a767SRodney W. Grimes } 1319a316d390SJohn Dyson start += 1; 1320a316d390SJohn Dyson size -= 1; 1321df8bae1dSRodney W. Grimes } 1322df8bae1dSRodney W. Grimes } 1323f919ebdeSDavid Greenman vm_object_pip_wakeup(object); 1324c0503609SDavid Greenman } 1325df8bae1dSRodney W. Grimes 1326df8bae1dSRodney W. Grimes /* 1327df8bae1dSRodney W. Grimes * Routine: vm_object_coalesce 1328df8bae1dSRodney W. Grimes * Function: Coalesces two objects backing up adjoining 1329df8bae1dSRodney W. Grimes * regions of memory into a single object. 1330df8bae1dSRodney W. Grimes * 1331df8bae1dSRodney W. Grimes * returns TRUE if objects were combined. 1332df8bae1dSRodney W. Grimes * 1333df8bae1dSRodney W. Grimes * NOTE: Only works at the moment if the second object is NULL - 1334df8bae1dSRodney W. Grimes * if it's not, which object do we lock first? 1335df8bae1dSRodney W. Grimes * 1336df8bae1dSRodney W. Grimes * Parameters: 1337df8bae1dSRodney W. Grimes * prev_object First object to coalesce 1338df8bae1dSRodney W. Grimes * prev_offset Offset into prev_object 1339df8bae1dSRodney W. Grimes * next_object Second object into coalesce 1340df8bae1dSRodney W. Grimes * next_offset Offset into next_object 1341df8bae1dSRodney W. Grimes * 1342df8bae1dSRodney W. Grimes * prev_size Size of reference to prev_object 1343df8bae1dSRodney W. Grimes * next_size Size of reference to next_object 1344df8bae1dSRodney W. Grimes * 1345df8bae1dSRodney W. Grimes * Conditions: 1346df8bae1dSRodney W. Grimes * The object must *not* be locked. 1347df8bae1dSRodney W. Grimes */ 13480d94caffSDavid Greenman boolean_t 1349a316d390SJohn Dyson vm_object_coalesce(prev_object, prev_pindex, prev_size, next_size) 1350df8bae1dSRodney W. Grimes register vm_object_t prev_object; 1351a316d390SJohn Dyson vm_pindex_t prev_pindex; 1352df8bae1dSRodney W. Grimes vm_size_t prev_size, next_size; 1353df8bae1dSRodney W. Grimes { 1354df8bae1dSRodney W. Grimes vm_size_t newsize; 1355df8bae1dSRodney W. Grimes 1356df8bae1dSRodney W. Grimes if (prev_object == NULL) { 1357df8bae1dSRodney W. Grimes return (TRUE); 1358df8bae1dSRodney W. Grimes } 1359df8bae1dSRodney W. Grimes 136030dcfc09SJohn Dyson if (prev_object->type != OBJT_DEFAULT) { 136130dcfc09SJohn Dyson return (FALSE); 136230dcfc09SJohn Dyson } 136330dcfc09SJohn Dyson 1364df8bae1dSRodney W. Grimes /* 1365df8bae1dSRodney W. Grimes * Try to collapse the object first 1366df8bae1dSRodney W. Grimes */ 1367df8bae1dSRodney W. Grimes vm_object_collapse(prev_object); 1368df8bae1dSRodney W. Grimes 1369df8bae1dSRodney W. Grimes /* 13700d94caffSDavid Greenman * Can't coalesce if: . more than one reference . paged out . shadows 13710d94caffSDavid Greenman * another object . has a copy elsewhere (any of which mean that the 13720d94caffSDavid Greenman * pages not mapped to prev_entry may be in use anyway) 1373df8bae1dSRodney W. Grimes */ 1374df8bae1dSRodney W. Grimes 13758cc7e047SJohn Dyson if (prev_object->backing_object != NULL) { 1376df8bae1dSRodney W. Grimes return (FALSE); 1377df8bae1dSRodney W. Grimes } 1378a316d390SJohn Dyson 1379a316d390SJohn Dyson prev_size >>= PAGE_SHIFT; 1380a316d390SJohn Dyson next_size >>= PAGE_SHIFT; 13818cc7e047SJohn Dyson 13828cc7e047SJohn Dyson if ((prev_object->ref_count > 1) && 13838cc7e047SJohn Dyson (prev_object->size != prev_pindex + prev_size)) { 13848cc7e047SJohn Dyson return (FALSE); 13858cc7e047SJohn Dyson } 13868cc7e047SJohn Dyson 1387df8bae1dSRodney W. Grimes /* 13880d94caffSDavid Greenman * Remove any pages that may still be in the object from a previous 13890d94caffSDavid Greenman * deallocation. 1390df8bae1dSRodney W. Grimes */ 1391df8bae1dSRodney W. Grimes 1392df8bae1dSRodney W. Grimes vm_object_page_remove(prev_object, 1393a316d390SJohn Dyson prev_pindex + prev_size, 1394a316d390SJohn Dyson prev_pindex + prev_size + next_size, FALSE); 1395df8bae1dSRodney W. Grimes 1396df8bae1dSRodney W. Grimes /* 1397df8bae1dSRodney W. Grimes * Extend the object if necessary. 1398df8bae1dSRodney W. Grimes */ 1399a316d390SJohn Dyson newsize = prev_pindex + prev_size + next_size; 1400df8bae1dSRodney W. Grimes if (newsize > prev_object->size) 1401df8bae1dSRodney W. Grimes prev_object->size = newsize; 1402df8bae1dSRodney W. Grimes 1403df8bae1dSRodney W. Grimes return (TRUE); 1404df8bae1dSRodney W. Grimes } 1405df8bae1dSRodney W. Grimes 1406c7c34a24SBruce Evans #include "opt_ddb.h" 1407c3cb3e12SDavid Greenman #ifdef DDB 1408c7c34a24SBruce Evans #include <sys/kernel.h> 1409c7c34a24SBruce Evans 1410c7c34a24SBruce Evans #include <machine/cons.h> 1411c7c34a24SBruce Evans 1412c7c34a24SBruce Evans #include <ddb/ddb.h> 1413c7c34a24SBruce Evans 1414c7c34a24SBruce Evans static int _vm_object_in_map __P((vm_map_t map, vm_object_t object, 1415c7c34a24SBruce Evans vm_map_entry_t entry)); 1416c7c34a24SBruce Evans static int vm_object_in_map __P((vm_object_t object)); 1417c3cb3e12SDavid Greenman 1418cac597e4SBruce Evans static int 1419a1f6d91cSDavid Greenman _vm_object_in_map(map, object, entry) 1420a1f6d91cSDavid Greenman vm_map_t map; 1421a1f6d91cSDavid Greenman vm_object_t object; 1422a1f6d91cSDavid Greenman vm_map_entry_t entry; 1423a1f6d91cSDavid Greenman { 1424a1f6d91cSDavid Greenman vm_map_t tmpm; 1425a1f6d91cSDavid Greenman vm_map_entry_t tmpe; 1426a1f6d91cSDavid Greenman vm_object_t obj; 1427a1f6d91cSDavid Greenman int entcount; 1428a1f6d91cSDavid Greenman 1429a1f6d91cSDavid Greenman if (map == 0) 1430a1f6d91cSDavid Greenman return 0; 1431a1f6d91cSDavid Greenman 1432a1f6d91cSDavid Greenman if (entry == 0) { 1433a1f6d91cSDavid Greenman tmpe = map->header.next; 1434a1f6d91cSDavid Greenman entcount = map->nentries; 1435a1f6d91cSDavid Greenman while (entcount-- && (tmpe != &map->header)) { 1436a1f6d91cSDavid Greenman if( _vm_object_in_map(map, object, tmpe)) { 1437a1f6d91cSDavid Greenman return 1; 1438a1f6d91cSDavid Greenman } 1439a1f6d91cSDavid Greenman tmpe = tmpe->next; 1440a1f6d91cSDavid Greenman } 1441afa07f7eSJohn Dyson } else if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) { 1442a1f6d91cSDavid Greenman tmpm = entry->object.share_map; 1443a1f6d91cSDavid Greenman tmpe = tmpm->header.next; 1444a1f6d91cSDavid Greenman entcount = tmpm->nentries; 1445a1f6d91cSDavid Greenman while (entcount-- && tmpe != &tmpm->header) { 1446a1f6d91cSDavid Greenman if( _vm_object_in_map(tmpm, object, tmpe)) { 1447a1f6d91cSDavid Greenman return 1; 1448a1f6d91cSDavid Greenman } 1449a1f6d91cSDavid Greenman tmpe = tmpe->next; 1450a1f6d91cSDavid Greenman } 1451a1f6d91cSDavid Greenman } else if (obj = entry->object.vm_object) { 145224a1cce3SDavid Greenman for(; obj; obj=obj->backing_object) 1453a1f6d91cSDavid Greenman if( obj == object) { 1454a1f6d91cSDavid Greenman return 1; 1455a1f6d91cSDavid Greenman } 1456a1f6d91cSDavid Greenman } 1457a1f6d91cSDavid Greenman return 0; 1458a1f6d91cSDavid Greenman } 1459a1f6d91cSDavid Greenman 1460cac597e4SBruce Evans static int 1461a1f6d91cSDavid Greenman vm_object_in_map( object) 1462a1f6d91cSDavid Greenman vm_object_t object; 1463a1f6d91cSDavid Greenman { 1464a1f6d91cSDavid Greenman struct proc *p; 14651b67ec6dSJeffrey Hsu for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 1466a1f6d91cSDavid Greenman if( !p->p_vmspace /* || (p->p_flag & (P_SYSTEM|P_WEXIT)) */) 1467a1f6d91cSDavid Greenman continue; 1468a1f6d91cSDavid Greenman if( _vm_object_in_map(&p->p_vmspace->vm_map, object, 0)) 1469a1f6d91cSDavid Greenman return 1; 1470a1f6d91cSDavid Greenman } 1471a1f6d91cSDavid Greenman if( _vm_object_in_map( kernel_map, object, 0)) 1472a1f6d91cSDavid Greenman return 1; 1473a1f6d91cSDavid Greenman if( _vm_object_in_map( kmem_map, object, 0)) 1474a1f6d91cSDavid Greenman return 1; 1475a1f6d91cSDavid Greenman if( _vm_object_in_map( pager_map, object, 0)) 1476a1f6d91cSDavid Greenman return 1; 1477a1f6d91cSDavid Greenman if( _vm_object_in_map( buffer_map, object, 0)) 1478a1f6d91cSDavid Greenman return 1; 1479a1f6d91cSDavid Greenman if( _vm_object_in_map( io_map, object, 0)) 1480a1f6d91cSDavid Greenman return 1; 1481a1f6d91cSDavid Greenman if( _vm_object_in_map( phys_map, object, 0)) 1482a1f6d91cSDavid Greenman return 1; 1483a1f6d91cSDavid Greenman if( _vm_object_in_map( mb_map, object, 0)) 1484a1f6d91cSDavid Greenman return 1; 1485a1f6d91cSDavid Greenman if( _vm_object_in_map( u_map, object, 0)) 1486a1f6d91cSDavid Greenman return 1; 1487a1f6d91cSDavid Greenman return 0; 1488a1f6d91cSDavid Greenman } 1489a1f6d91cSDavid Greenman 1490c7c34a24SBruce Evans DB_SHOW_COMMAND(vmochk, vm_object_check) 1491f708ef1bSPoul-Henning Kamp { 1492a1f6d91cSDavid Greenman vm_object_t object; 1493a1f6d91cSDavid Greenman 1494a1f6d91cSDavid Greenman /* 1495a1f6d91cSDavid Greenman * make sure that internal objs are in a map somewhere 1496a1f6d91cSDavid Greenman * and none have zero ref counts. 1497a1f6d91cSDavid Greenman */ 1498b18bfc3dSJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 1499a1f6d91cSDavid Greenman object != NULL; 1500b18bfc3dSJohn Dyson object = TAILQ_NEXT(object, object_list)) { 150124a1cce3SDavid Greenman if (object->handle == NULL && 150224a1cce3SDavid Greenman (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) { 1503a1f6d91cSDavid Greenman if (object->ref_count == 0) { 1504c7c34a24SBruce Evans db_printf("vmochk: internal obj has zero ref count: %d\n", 1505a1f6d91cSDavid Greenman object->size); 1506a1f6d91cSDavid Greenman } 1507a1f6d91cSDavid Greenman if (!vm_object_in_map(object)) { 1508c7c34a24SBruce Evans db_printf("vmochk: internal obj is not in a map: " 15093af76890SPoul-Henning Kamp "ref: %d, size: %d: 0x%x, backing_object: 0x%x\n", 15103af76890SPoul-Henning Kamp object->ref_count, object->size, 15113af76890SPoul-Henning Kamp object->size, object->backing_object); 1512a1f6d91cSDavid Greenman } 1513a1f6d91cSDavid Greenman } 1514a1f6d91cSDavid Greenman } 1515a1f6d91cSDavid Greenman } 1516a1f6d91cSDavid Greenman 151726f9a767SRodney W. Grimes /* 1518df8bae1dSRodney W. Grimes * vm_object_print: [ debug ] 1519df8bae1dSRodney W. Grimes */ 1520c7c34a24SBruce Evans DB_SHOW_COMMAND(object, vm_object_print_static) 1521df8bae1dSRodney W. Grimes { 1522c7c34a24SBruce Evans /* XXX convert args. */ 1523c7c34a24SBruce Evans vm_object_t object = (vm_object_t)addr; 1524c7c34a24SBruce Evans boolean_t full = have_addr; 1525c7c34a24SBruce Evans 1526df8bae1dSRodney W. Grimes register vm_page_t p; 1527df8bae1dSRodney W. Grimes 1528c7c34a24SBruce Evans /* XXX count is an (unused) arg. Avoid shadowing it. */ 1529c7c34a24SBruce Evans #define count was_count 1530c7c34a24SBruce Evans 1531df8bae1dSRodney W. Grimes register int count; 1532df8bae1dSRodney W. Grimes 1533df8bae1dSRodney W. Grimes if (object == NULL) 1534df8bae1dSRodney W. Grimes return; 1535df8bae1dSRodney W. Grimes 153695e5e988SJohn Dyson db_iprintf("Object 0x%x: type=%d, size=0x%x, res=%d, ref=%d, flags=0x%x\n", 153795e5e988SJohn Dyson (int) object, (int) object->type, (int) object->size, 153895e5e988SJohn Dyson object->resident_page_count, 153995e5e988SJohn Dyson object->ref_count, 154095e5e988SJohn Dyson object->flags); 154195e5e988SJohn Dyson db_iprintf(" sref=%d, offset=0x%x, backing_object(%d)=(0x%x)+0x%x\n", 154295e5e988SJohn Dyson object->shadow_count, 15432a4895f4SDavid Greenman (int) object->paging_offset, 154495e5e988SJohn Dyson (((int)object->backing_object)?object->backing_object->ref_count:0), 154595e5e988SJohn Dyson (int) object->backing_object, 154695e5e988SJohn Dyson (int) object->backing_object_offset); 1547df8bae1dSRodney W. Grimes 1548df8bae1dSRodney W. Grimes if (!full) 1549df8bae1dSRodney W. Grimes return; 1550df8bae1dSRodney W. Grimes 1551c7c34a24SBruce Evans db_indent += 2; 1552df8bae1dSRodney W. Grimes count = 0; 1553b18bfc3dSJohn Dyson for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) { 1554df8bae1dSRodney W. Grimes if (count == 0) 1555c7c34a24SBruce Evans db_iprintf("memory:="); 1556df8bae1dSRodney W. Grimes else if (count == 6) { 1557c7c34a24SBruce Evans db_printf("\n"); 1558c7c34a24SBruce Evans db_iprintf(" ..."); 1559df8bae1dSRodney W. Grimes count = 0; 1560df8bae1dSRodney W. Grimes } else 1561c7c34a24SBruce Evans db_printf(","); 1562df8bae1dSRodney W. Grimes count++; 1563df8bae1dSRodney W. Grimes 1564c7c34a24SBruce Evans db_printf("(off=0x%lx,page=0x%lx)", 1565a316d390SJohn Dyson (u_long) p->pindex, (u_long) VM_PAGE_TO_PHYS(p)); 1566df8bae1dSRodney W. Grimes } 1567df8bae1dSRodney W. Grimes if (count != 0) 1568c7c34a24SBruce Evans db_printf("\n"); 1569c7c34a24SBruce Evans db_indent -= 2; 1570df8bae1dSRodney W. Grimes } 15715070c7f8SJohn Dyson 1572c7c34a24SBruce Evans /* XXX. */ 1573c7c34a24SBruce Evans #undef count 1574c7c34a24SBruce Evans 1575c7c34a24SBruce Evans /* XXX need this non-static entry for calling from vm_map_print. */ 15765070c7f8SJohn Dyson void 1577c7c34a24SBruce Evans vm_object_print(addr, have_addr, count, modif) 1578c7c34a24SBruce Evans db_expr_t addr; 1579c7c34a24SBruce Evans boolean_t have_addr; 1580c7c34a24SBruce Evans db_expr_t count; 1581c7c34a24SBruce Evans char *modif; 1582c7c34a24SBruce Evans { 1583c7c34a24SBruce Evans vm_object_print_static(addr, have_addr, count, modif); 1584c7c34a24SBruce Evans } 1585c7c34a24SBruce Evans 1586c7c34a24SBruce Evans DB_SHOW_COMMAND(vmopag, vm_object_print_pages) 15875070c7f8SJohn Dyson { 15885070c7f8SJohn Dyson vm_object_t object; 15895070c7f8SJohn Dyson int nl = 0; 15905070c7f8SJohn Dyson int c; 15915070c7f8SJohn Dyson for (object = TAILQ_FIRST(&vm_object_list); 15925070c7f8SJohn Dyson object != NULL; 15935070c7f8SJohn Dyson object = TAILQ_NEXT(object, object_list)) { 15945070c7f8SJohn Dyson vm_pindex_t idx, fidx; 15955070c7f8SJohn Dyson vm_pindex_t osize; 15965070c7f8SJohn Dyson vm_offset_t pa = -1, padiff; 15975070c7f8SJohn Dyson int rcount; 15985070c7f8SJohn Dyson vm_page_t m; 15995070c7f8SJohn Dyson 16005070c7f8SJohn Dyson db_printf("new object: 0x%x\n", object); 16015070c7f8SJohn Dyson if ( nl > 18) { 16025070c7f8SJohn Dyson c = cngetc(); 16035070c7f8SJohn Dyson if (c != ' ') 16045070c7f8SJohn Dyson return; 16055070c7f8SJohn Dyson nl = 0; 16065070c7f8SJohn Dyson } 16075070c7f8SJohn Dyson nl++; 16085070c7f8SJohn Dyson rcount = 0; 16095070c7f8SJohn Dyson fidx = 0; 16105070c7f8SJohn Dyson osize = object->size; 16115070c7f8SJohn Dyson if (osize > 128) 16125070c7f8SJohn Dyson osize = 128; 16135070c7f8SJohn Dyson for(idx=0;idx<osize;idx++) { 16145070c7f8SJohn Dyson m = vm_page_lookup(object, idx); 16155070c7f8SJohn Dyson if (m == NULL) { 16165070c7f8SJohn Dyson if (rcount) { 16175070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", 16185070c7f8SJohn Dyson fidx, rcount, pa); 16195070c7f8SJohn Dyson if ( nl > 18) { 16205070c7f8SJohn Dyson c = cngetc(); 16215070c7f8SJohn Dyson if (c != ' ') 16225070c7f8SJohn Dyson return; 16235070c7f8SJohn Dyson nl = 0; 16245070c7f8SJohn Dyson } 16255070c7f8SJohn Dyson nl++; 16265070c7f8SJohn Dyson rcount = 0; 16275070c7f8SJohn Dyson } 16285070c7f8SJohn Dyson continue; 16295070c7f8SJohn Dyson } 16305070c7f8SJohn Dyson 16315070c7f8SJohn Dyson 16325070c7f8SJohn Dyson if (rcount && 16335070c7f8SJohn Dyson (VM_PAGE_TO_PHYS(m) == pa + rcount * PAGE_SIZE)) { 16345070c7f8SJohn Dyson ++rcount; 16355070c7f8SJohn Dyson continue; 16365070c7f8SJohn Dyson } 16375070c7f8SJohn Dyson if (rcount) { 16385070c7f8SJohn Dyson padiff = pa + rcount * PAGE_SIZE - VM_PAGE_TO_PHYS(m); 16395070c7f8SJohn Dyson padiff >>= PAGE_SHIFT; 16405070c7f8SJohn Dyson padiff &= PQ_L2_MASK; 16415070c7f8SJohn Dyson if (padiff == 0) { 16425070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m) - rcount * PAGE_SIZE; 16435070c7f8SJohn Dyson ++rcount; 16445070c7f8SJohn Dyson continue; 16455070c7f8SJohn Dyson } 16465070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)", fidx, rcount, pa); 16475070c7f8SJohn Dyson db_printf("pd(%d)\n", padiff); 16485070c7f8SJohn Dyson if ( nl > 18) { 16495070c7f8SJohn Dyson c = cngetc(); 16505070c7f8SJohn Dyson if (c != ' ') 16515070c7f8SJohn Dyson return; 16525070c7f8SJohn Dyson nl = 0; 16535070c7f8SJohn Dyson } 16545070c7f8SJohn Dyson nl++; 16555070c7f8SJohn Dyson } 16565070c7f8SJohn Dyson fidx = idx; 16575070c7f8SJohn Dyson pa = VM_PAGE_TO_PHYS(m); 16585070c7f8SJohn Dyson rcount = 1; 16595070c7f8SJohn Dyson } 16605070c7f8SJohn Dyson if (rcount) { 16615070c7f8SJohn Dyson db_printf(" index(%d)run(%d)pa(0x%x)\n", fidx, rcount, pa); 16625070c7f8SJohn Dyson if ( nl > 18) { 16635070c7f8SJohn Dyson c = cngetc(); 16645070c7f8SJohn Dyson if (c != ' ') 16655070c7f8SJohn Dyson return; 16665070c7f8SJohn Dyson nl = 0; 16675070c7f8SJohn Dyson } 16685070c7f8SJohn Dyson nl++; 16695070c7f8SJohn Dyson } 16705070c7f8SJohn Dyson } 16715070c7f8SJohn Dyson } 1672c3cb3e12SDavid Greenman #endif /* DDB */ 1673