1*45748Smckusick /* 2*45748Smckusick * Copyright (c) 1985, Avadis Tevanian, Jr., Michael Wayne Young 3*45748Smckusick * Copyright (c) 1987 Carnegie-Mellon University 4*45748Smckusick * Copyright (c) 1991 Regents of the University of California. 5*45748Smckusick * All rights reserved. 6*45748Smckusick * 7*45748Smckusick * This code is derived from software contributed to Berkeley by 8*45748Smckusick * The Mach Operating System project at Carnegie-Mellon University. 9*45748Smckusick * 10*45748Smckusick * The CMU software License Agreement specifies the terms and conditions 11*45748Smckusick * for use and redistribution. 12*45748Smckusick * 13*45748Smckusick * @(#)vm_object.c 7.1 (Berkeley) 12/05/90 14*45748Smckusick */ 15*45748Smckusick 16*45748Smckusick /* 17*45748Smckusick * Virtual memory object module. 18*45748Smckusick */ 19*45748Smckusick 20*45748Smckusick #include "param.h" 21*45748Smckusick #include "malloc.h" 22*45748Smckusick #include "../vm/vm_param.h" 23*45748Smckusick #include "lock.h" 24*45748Smckusick #include "../vm/vm_page.h" 25*45748Smckusick #include "../vm/vm_map.h" 26*45748Smckusick #include "../vm/vm_object.h" 27*45748Smckusick 28*45748Smckusick /* 29*45748Smckusick * Virtual memory objects maintain the actual data 30*45748Smckusick * associated with allocated virtual memory. A given 31*45748Smckusick * page of memory exists within exactly one object. 32*45748Smckusick * 33*45748Smckusick * An object is only deallocated when all "references" 34*45748Smckusick * are given up. Only one "reference" to a given 35*45748Smckusick * region of an object should be writeable. 36*45748Smckusick * 37*45748Smckusick * Associated with each object is a list of all resident 38*45748Smckusick * memory pages belonging to that object; this list is 39*45748Smckusick * maintained by the "vm_page" module, and locked by the object's 40*45748Smckusick * lock. 41*45748Smckusick * 42*45748Smckusick * Each object also records a "pager" routine which is 43*45748Smckusick * used to retrieve (and store) pages to the proper backing 44*45748Smckusick * storage. In addition, objects may be backed by other 45*45748Smckusick * objects from which they were virtual-copied. 46*45748Smckusick * 47*45748Smckusick * The only items within the object structure which are 48*45748Smckusick * modified after time of creation are: 49*45748Smckusick * reference count locked by object's lock 50*45748Smckusick * pager routine locked by object's lock 51*45748Smckusick * 52*45748Smckusick */ 53*45748Smckusick 54*45748Smckusick struct vm_object kernel_object_store; 55*45748Smckusick struct vm_object kmem_object_store; 56*45748Smckusick 57*45748Smckusick #define VM_OBJECT_HASH_COUNT 157 58*45748Smckusick 59*45748Smckusick int vm_cache_max = 100; /* can patch if necessary */ 60*45748Smckusick queue_head_t vm_object_hashtable[VM_OBJECT_HASH_COUNT]; 61*45748Smckusick 62*45748Smckusick long object_collapses = 0; 63*45748Smckusick long object_bypasses = 0; 64*45748Smckusick 65*45748Smckusick /* 66*45748Smckusick * vm_object_init: 67*45748Smckusick * 68*45748Smckusick * Initialize the VM objects module. 69*45748Smckusick */ 70*45748Smckusick void vm_object_init() 71*45748Smckusick { 72*45748Smckusick register int i; 73*45748Smckusick 74*45748Smckusick queue_init(&vm_object_cached_list); 75*45748Smckusick queue_init(&vm_object_list); 76*45748Smckusick vm_object_count = 0; 77*45748Smckusick simple_lock_init(&vm_cache_lock); 78*45748Smckusick simple_lock_init(&vm_object_list_lock); 79*45748Smckusick 80*45748Smckusick for (i = 0; i < VM_OBJECT_HASH_COUNT; i++) 81*45748Smckusick queue_init(&vm_object_hashtable[i]); 82*45748Smckusick 83*45748Smckusick kernel_object = &kernel_object_store; 84*45748Smckusick _vm_object_allocate(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS, 85*45748Smckusick kernel_object); 86*45748Smckusick 87*45748Smckusick kmem_object = &kmem_object_store; 88*45748Smckusick _vm_object_allocate(VM_KMEM_SIZE + VM_MBUF_SIZE, kmem_object); 89*45748Smckusick } 90*45748Smckusick 91*45748Smckusick /* 92*45748Smckusick * vm_object_allocate: 93*45748Smckusick * 94*45748Smckusick * Returns a new object with the given size. 95*45748Smckusick */ 96*45748Smckusick 97*45748Smckusick vm_object_t vm_object_allocate(size) 98*45748Smckusick vm_size_t size; 99*45748Smckusick { 100*45748Smckusick register vm_object_t result; 101*45748Smckusick 102*45748Smckusick result = (vm_object_t) 103*45748Smckusick malloc((u_long)sizeof *result, M_VMOBJ, M_WAITOK); 104*45748Smckusick 105*45748Smckusick _vm_object_allocate(size, result); 106*45748Smckusick 107*45748Smckusick return(result); 108*45748Smckusick } 109*45748Smckusick 110*45748Smckusick _vm_object_allocate(size, object) 111*45748Smckusick vm_size_t size; 112*45748Smckusick register vm_object_t object; 113*45748Smckusick { 114*45748Smckusick queue_init(&object->memq); 115*45748Smckusick vm_object_lock_init(object); 116*45748Smckusick object->ref_count = 1; 117*45748Smckusick object->resident_page_count = 0; 118*45748Smckusick object->size = size; 119*45748Smckusick object->can_persist = FALSE; 120*45748Smckusick object->paging_in_progress = 0; 121*45748Smckusick object->copy = VM_OBJECT_NULL; 122*45748Smckusick 123*45748Smckusick /* 124*45748Smckusick * Object starts out read-write, with no pager. 125*45748Smckusick */ 126*45748Smckusick 127*45748Smckusick object->pager = vm_pager_null; 128*45748Smckusick object->pager_ready = FALSE; 129*45748Smckusick object->internal = TRUE; /* vm_allocate_with_pager will reset */ 130*45748Smckusick object->paging_offset = 0; 131*45748Smckusick object->shadow = VM_OBJECT_NULL; 132*45748Smckusick object->shadow_offset = (vm_offset_t) 0; 133*45748Smckusick 134*45748Smckusick simple_lock(&vm_object_list_lock); 135*45748Smckusick queue_enter(&vm_object_list, object, vm_object_t, object_list); 136*45748Smckusick vm_object_count++; 137*45748Smckusick simple_unlock(&vm_object_list_lock); 138*45748Smckusick } 139*45748Smckusick 140*45748Smckusick /* 141*45748Smckusick * vm_object_reference: 142*45748Smckusick * 143*45748Smckusick * Gets another reference to the given object. 144*45748Smckusick */ 145*45748Smckusick void vm_object_reference(object) 146*45748Smckusick register vm_object_t object; 147*45748Smckusick { 148*45748Smckusick if (object == VM_OBJECT_NULL) 149*45748Smckusick return; 150*45748Smckusick 151*45748Smckusick vm_object_lock(object); 152*45748Smckusick object->ref_count++; 153*45748Smckusick vm_object_unlock(object); 154*45748Smckusick } 155*45748Smckusick 156*45748Smckusick /* 157*45748Smckusick * vm_object_deallocate: 158*45748Smckusick * 159*45748Smckusick * Release a reference to the specified object, 160*45748Smckusick * gained either through a vm_object_allocate 161*45748Smckusick * or a vm_object_reference call. When all references 162*45748Smckusick * are gone, storage associated with this object 163*45748Smckusick * may be relinquished. 164*45748Smckusick * 165*45748Smckusick * No object may be locked. 166*45748Smckusick */ 167*45748Smckusick void vm_object_deallocate(object) 168*45748Smckusick register vm_object_t object; 169*45748Smckusick { 170*45748Smckusick vm_object_t temp; 171*45748Smckusick 172*45748Smckusick while (object != VM_OBJECT_NULL) { 173*45748Smckusick 174*45748Smckusick /* 175*45748Smckusick * The cache holds a reference (uncounted) to 176*45748Smckusick * the object; we must lock it before removing 177*45748Smckusick * the object. 178*45748Smckusick */ 179*45748Smckusick 180*45748Smckusick vm_object_cache_lock(); 181*45748Smckusick 182*45748Smckusick /* 183*45748Smckusick * Lose the reference 184*45748Smckusick */ 185*45748Smckusick vm_object_lock(object); 186*45748Smckusick if (--(object->ref_count) != 0) { 187*45748Smckusick 188*45748Smckusick /* 189*45748Smckusick * If there are still references, then 190*45748Smckusick * we are done. 191*45748Smckusick */ 192*45748Smckusick vm_object_unlock(object); 193*45748Smckusick vm_object_cache_unlock(); 194*45748Smckusick return; 195*45748Smckusick } 196*45748Smckusick 197*45748Smckusick /* 198*45748Smckusick * See if this object can persist. If so, enter 199*45748Smckusick * it in the cache, then deactivate all of its 200*45748Smckusick * pages. 201*45748Smckusick */ 202*45748Smckusick 203*45748Smckusick if (object->can_persist) { 204*45748Smckusick 205*45748Smckusick queue_enter(&vm_object_cached_list, object, 206*45748Smckusick vm_object_t, cached_list); 207*45748Smckusick vm_object_cached++; 208*45748Smckusick vm_object_cache_unlock(); 209*45748Smckusick 210*45748Smckusick vm_object_deactivate_pages(object); 211*45748Smckusick vm_object_unlock(object); 212*45748Smckusick 213*45748Smckusick vm_object_cache_trim(); 214*45748Smckusick return; 215*45748Smckusick } 216*45748Smckusick 217*45748Smckusick /* 218*45748Smckusick * Make sure no one can look us up now. 219*45748Smckusick */ 220*45748Smckusick vm_object_remove(object->pager); 221*45748Smckusick vm_object_cache_unlock(); 222*45748Smckusick 223*45748Smckusick temp = object->shadow; 224*45748Smckusick vm_object_terminate(object); 225*45748Smckusick /* unlocks and deallocates object */ 226*45748Smckusick object = temp; 227*45748Smckusick } 228*45748Smckusick } 229*45748Smckusick 230*45748Smckusick 231*45748Smckusick /* 232*45748Smckusick * vm_object_terminate actually destroys the specified object, freeing 233*45748Smckusick * up all previously used resources. 234*45748Smckusick * 235*45748Smckusick * The object must be locked. 236*45748Smckusick */ 237*45748Smckusick void vm_object_terminate(object) 238*45748Smckusick register vm_object_t object; 239*45748Smckusick { 240*45748Smckusick register vm_page_t p; 241*45748Smckusick vm_object_t shadow_object; 242*45748Smckusick 243*45748Smckusick /* 244*45748Smckusick * Detach the object from its shadow if we are the shadow's 245*45748Smckusick * copy. 246*45748Smckusick */ 247*45748Smckusick if ((shadow_object = object->shadow) != VM_OBJECT_NULL) { 248*45748Smckusick vm_object_lock(shadow_object); 249*45748Smckusick if (shadow_object->copy == object) 250*45748Smckusick shadow_object->copy = VM_OBJECT_NULL; 251*45748Smckusick #if 0 252*45748Smckusick else if (shadow_object->copy != VM_OBJECT_NULL) 253*45748Smckusick panic("vm_object_terminate: copy/shadow inconsistency"); 254*45748Smckusick #endif 255*45748Smckusick vm_object_unlock(shadow_object); 256*45748Smckusick } 257*45748Smckusick 258*45748Smckusick /* 259*45748Smckusick * Wait until the pageout daemon is through 260*45748Smckusick * with the object. 261*45748Smckusick */ 262*45748Smckusick 263*45748Smckusick while (object->paging_in_progress != 0) { 264*45748Smckusick vm_object_sleep(object, object, FALSE); 265*45748Smckusick vm_object_lock(object); 266*45748Smckusick } 267*45748Smckusick 268*45748Smckusick 269*45748Smckusick /* 270*45748Smckusick * While the paging system is locked, 271*45748Smckusick * pull the object's pages off the active 272*45748Smckusick * and inactive queues. This keeps the 273*45748Smckusick * pageout daemon from playing with them 274*45748Smckusick * during vm_pager_deallocate. 275*45748Smckusick * 276*45748Smckusick * We can't free the pages yet, because the 277*45748Smckusick * object's pager may have to write them out 278*45748Smckusick * before deallocating the paging space. 279*45748Smckusick */ 280*45748Smckusick 281*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 282*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 283*45748Smckusick VM_PAGE_CHECK(p); 284*45748Smckusick 285*45748Smckusick vm_page_lock_queues(); 286*45748Smckusick if (p->active) { 287*45748Smckusick queue_remove(&vm_page_queue_active, p, vm_page_t, 288*45748Smckusick pageq); 289*45748Smckusick p->active = FALSE; 290*45748Smckusick vm_page_active_count--; 291*45748Smckusick } 292*45748Smckusick 293*45748Smckusick if (p->inactive) { 294*45748Smckusick queue_remove(&vm_page_queue_inactive, p, vm_page_t, 295*45748Smckusick pageq); 296*45748Smckusick p->inactive = FALSE; 297*45748Smckusick vm_page_inactive_count--; 298*45748Smckusick } 299*45748Smckusick vm_page_unlock_queues(); 300*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 301*45748Smckusick } 302*45748Smckusick 303*45748Smckusick vm_object_unlock(object); 304*45748Smckusick 305*45748Smckusick if (object->paging_in_progress != 0) 306*45748Smckusick panic("vm_object_deallocate: pageout in progress"); 307*45748Smckusick 308*45748Smckusick /* 309*45748Smckusick * Clean and free the pages, as appropriate. 310*45748Smckusick * All references to the object are gone, 311*45748Smckusick * so we don't need to lock it. 312*45748Smckusick */ 313*45748Smckusick 314*45748Smckusick if (!object->internal) { 315*45748Smckusick vm_object_lock(object); 316*45748Smckusick vm_object_page_clean(object, 0, 0); 317*45748Smckusick vm_object_unlock(object); 318*45748Smckusick } 319*45748Smckusick while (!queue_empty(&object->memq)) { 320*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 321*45748Smckusick 322*45748Smckusick VM_PAGE_CHECK(p); 323*45748Smckusick 324*45748Smckusick vm_page_lock_queues(); 325*45748Smckusick vm_page_free(p); 326*45748Smckusick vm_page_unlock_queues(); 327*45748Smckusick } 328*45748Smckusick 329*45748Smckusick /* 330*45748Smckusick * Let the pager know object is dead. 331*45748Smckusick */ 332*45748Smckusick 333*45748Smckusick if (object->pager != vm_pager_null) 334*45748Smckusick vm_pager_deallocate(object->pager); 335*45748Smckusick 336*45748Smckusick 337*45748Smckusick simple_lock(&vm_object_list_lock); 338*45748Smckusick queue_remove(&vm_object_list, object, vm_object_t, object_list); 339*45748Smckusick vm_object_count--; 340*45748Smckusick simple_unlock(&vm_object_list_lock); 341*45748Smckusick 342*45748Smckusick /* 343*45748Smckusick * Free the space for the object. 344*45748Smckusick */ 345*45748Smckusick 346*45748Smckusick free((caddr_t)object, M_VMOBJ); 347*45748Smckusick } 348*45748Smckusick 349*45748Smckusick /* 350*45748Smckusick * vm_object_page_clean 351*45748Smckusick * 352*45748Smckusick * Clean all dirty pages in the specified range of object. 353*45748Smckusick * Leaves page on whatever queue it is currently on. 354*45748Smckusick * 355*45748Smckusick * Odd semantics: if start == end, we clean everything. 356*45748Smckusick * 357*45748Smckusick * The object must be locked. 358*45748Smckusick */ 359*45748Smckusick vm_object_page_clean(object, start, end) 360*45748Smckusick register vm_object_t object; 361*45748Smckusick register vm_offset_t start; 362*45748Smckusick register vm_offset_t end; 363*45748Smckusick { 364*45748Smckusick register vm_page_t p; 365*45748Smckusick 366*45748Smckusick if (object->pager == vm_pager_null) 367*45748Smckusick return; 368*45748Smckusick 369*45748Smckusick again: 370*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 371*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 372*45748Smckusick if (start == end || 373*45748Smckusick p->offset >= start && p->offset < end) { 374*45748Smckusick if (p->clean && pmap_is_modified(VM_PAGE_TO_PHYS(p))) 375*45748Smckusick p->clean = FALSE; 376*45748Smckusick pmap_remove_all(VM_PAGE_TO_PHYS(p)); 377*45748Smckusick if (!p->clean) { 378*45748Smckusick p->busy = TRUE; 379*45748Smckusick object->paging_in_progress++; 380*45748Smckusick vm_object_unlock(object); 381*45748Smckusick (void) vm_pager_put(object->pager, p, TRUE); 382*45748Smckusick vm_object_lock(object); 383*45748Smckusick object->paging_in_progress--; 384*45748Smckusick p->busy = FALSE; 385*45748Smckusick PAGE_WAKEUP(p); 386*45748Smckusick goto again; 387*45748Smckusick } 388*45748Smckusick } 389*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 390*45748Smckusick } 391*45748Smckusick } 392*45748Smckusick 393*45748Smckusick /* 394*45748Smckusick * vm_object_deactivate_pages 395*45748Smckusick * 396*45748Smckusick * Deactivate all pages in the specified object. (Keep its pages 397*45748Smckusick * in memory even though it is no longer referenced.) 398*45748Smckusick * 399*45748Smckusick * The object must be locked. 400*45748Smckusick */ 401*45748Smckusick vm_object_deactivate_pages(object) 402*45748Smckusick register vm_object_t object; 403*45748Smckusick { 404*45748Smckusick register vm_page_t p, next; 405*45748Smckusick 406*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 407*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 408*45748Smckusick next = (vm_page_t) queue_next(&p->listq); 409*45748Smckusick vm_page_lock_queues(); 410*45748Smckusick vm_page_deactivate(p); 411*45748Smckusick vm_page_unlock_queues(); 412*45748Smckusick p = next; 413*45748Smckusick } 414*45748Smckusick } 415*45748Smckusick 416*45748Smckusick /* 417*45748Smckusick * Trim the object cache to size. 418*45748Smckusick */ 419*45748Smckusick vm_object_cache_trim() 420*45748Smckusick { 421*45748Smckusick register vm_object_t object; 422*45748Smckusick 423*45748Smckusick vm_object_cache_lock(); 424*45748Smckusick while (vm_object_cached > vm_cache_max) { 425*45748Smckusick object = (vm_object_t) queue_first(&vm_object_cached_list); 426*45748Smckusick vm_object_cache_unlock(); 427*45748Smckusick 428*45748Smckusick if (object != vm_object_lookup(object->pager)) 429*45748Smckusick panic("vm_object_deactivate: I'm sooo confused."); 430*45748Smckusick 431*45748Smckusick pager_cache(object, FALSE); 432*45748Smckusick 433*45748Smckusick vm_object_cache_lock(); 434*45748Smckusick } 435*45748Smckusick vm_object_cache_unlock(); 436*45748Smckusick } 437*45748Smckusick 438*45748Smckusick 439*45748Smckusick /* 440*45748Smckusick * vm_object_shutdown() 441*45748Smckusick * 442*45748Smckusick * Shut down the object system. Unfortunately, while we 443*45748Smckusick * may be trying to do this, init is happily waiting for 444*45748Smckusick * processes to exit, and therefore will be causing some objects 445*45748Smckusick * to be deallocated. To handle this, we gain a fake reference 446*45748Smckusick * to all objects we release paging areas for. This will prevent 447*45748Smckusick * a duplicate deallocation. This routine is probably full of 448*45748Smckusick * race conditions! 449*45748Smckusick */ 450*45748Smckusick 451*45748Smckusick void vm_object_shutdown() 452*45748Smckusick { 453*45748Smckusick register vm_object_t object; 454*45748Smckusick 455*45748Smckusick /* 456*45748Smckusick * Clean up the object cache *before* we screw up the reference 457*45748Smckusick * counts on all of the objects. 458*45748Smckusick */ 459*45748Smckusick 460*45748Smckusick vm_object_cache_clear(); 461*45748Smckusick 462*45748Smckusick printf("free paging spaces: "); 463*45748Smckusick 464*45748Smckusick /* 465*45748Smckusick * First we gain a reference to each object so that 466*45748Smckusick * no one else will deallocate them. 467*45748Smckusick */ 468*45748Smckusick 469*45748Smckusick simple_lock(&vm_object_list_lock); 470*45748Smckusick object = (vm_object_t) queue_first(&vm_object_list); 471*45748Smckusick while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 472*45748Smckusick vm_object_reference(object); 473*45748Smckusick object = (vm_object_t) queue_next(&object->object_list); 474*45748Smckusick } 475*45748Smckusick simple_unlock(&vm_object_list_lock); 476*45748Smckusick 477*45748Smckusick /* 478*45748Smckusick * Now we deallocate all the paging areas. We don't need 479*45748Smckusick * to lock anything because we've reduced to a single 480*45748Smckusick * processor while shutting down. This also assumes that 481*45748Smckusick * no new objects are being created. 482*45748Smckusick */ 483*45748Smckusick 484*45748Smckusick object = (vm_object_t) queue_first(&vm_object_list); 485*45748Smckusick while (!queue_end(&vm_object_list, (queue_entry_t) object)) { 486*45748Smckusick if (object->pager != vm_pager_null) 487*45748Smckusick vm_pager_deallocate(object->pager); 488*45748Smckusick object = (vm_object_t) queue_next(&object->object_list); 489*45748Smckusick printf("."); 490*45748Smckusick } 491*45748Smckusick printf("done.\n"); 492*45748Smckusick } 493*45748Smckusick 494*45748Smckusick /* 495*45748Smckusick * vm_object_pmap_copy: 496*45748Smckusick * 497*45748Smckusick * Makes all physical pages in the specified 498*45748Smckusick * object range copy-on-write. No writeable 499*45748Smckusick * references to these pages should remain. 500*45748Smckusick * 501*45748Smckusick * The object must *not* be locked. 502*45748Smckusick */ 503*45748Smckusick void vm_object_pmap_copy(object, start, end) 504*45748Smckusick register vm_object_t object; 505*45748Smckusick register vm_offset_t start; 506*45748Smckusick register vm_offset_t end; 507*45748Smckusick { 508*45748Smckusick register vm_page_t p; 509*45748Smckusick 510*45748Smckusick if (object == VM_OBJECT_NULL) 511*45748Smckusick return; 512*45748Smckusick 513*45748Smckusick vm_object_lock(object); 514*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 515*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 516*45748Smckusick if ((start <= p->offset) && (p->offset < end)) { 517*45748Smckusick if (!p->copy_on_write) { 518*45748Smckusick pmap_copy_on_write(VM_PAGE_TO_PHYS(p)); 519*45748Smckusick p->copy_on_write = TRUE; 520*45748Smckusick } 521*45748Smckusick } 522*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 523*45748Smckusick } 524*45748Smckusick vm_object_unlock(object); 525*45748Smckusick } 526*45748Smckusick 527*45748Smckusick /* 528*45748Smckusick * vm_object_pmap_remove: 529*45748Smckusick * 530*45748Smckusick * Removes all physical pages in the specified 531*45748Smckusick * object range from all physical maps. 532*45748Smckusick * 533*45748Smckusick * The object must *not* be locked. 534*45748Smckusick */ 535*45748Smckusick void vm_object_pmap_remove(object, start, end) 536*45748Smckusick register vm_object_t object; 537*45748Smckusick register vm_offset_t start; 538*45748Smckusick register vm_offset_t end; 539*45748Smckusick { 540*45748Smckusick register vm_page_t p; 541*45748Smckusick 542*45748Smckusick if (object == VM_OBJECT_NULL) 543*45748Smckusick return; 544*45748Smckusick 545*45748Smckusick vm_object_lock(object); 546*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 547*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 548*45748Smckusick if ((start <= p->offset) && (p->offset < end)) { 549*45748Smckusick pmap_remove_all(VM_PAGE_TO_PHYS(p)); 550*45748Smckusick } 551*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 552*45748Smckusick } 553*45748Smckusick vm_object_unlock(object); 554*45748Smckusick } 555*45748Smckusick 556*45748Smckusick /* 557*45748Smckusick * vm_object_copy: 558*45748Smckusick * 559*45748Smckusick * Create a new object which is a copy of an existing 560*45748Smckusick * object, and mark all of the pages in the existing 561*45748Smckusick * object 'copy-on-write'. The new object has one reference. 562*45748Smckusick * Returns the new object. 563*45748Smckusick * 564*45748Smckusick * May defer the copy until later if the object is not backed 565*45748Smckusick * up by a non-default pager. 566*45748Smckusick */ 567*45748Smckusick void vm_object_copy(src_object, src_offset, size, 568*45748Smckusick dst_object, dst_offset, src_needs_copy) 569*45748Smckusick register vm_object_t src_object; 570*45748Smckusick vm_offset_t src_offset; 571*45748Smckusick vm_size_t size; 572*45748Smckusick vm_object_t *dst_object; /* OUT */ 573*45748Smckusick vm_offset_t *dst_offset; /* OUT */ 574*45748Smckusick boolean_t *src_needs_copy; /* OUT */ 575*45748Smckusick { 576*45748Smckusick register vm_object_t new_copy; 577*45748Smckusick register vm_object_t old_copy; 578*45748Smckusick vm_offset_t new_start, new_end; 579*45748Smckusick 580*45748Smckusick register vm_page_t p; 581*45748Smckusick 582*45748Smckusick if (src_object == VM_OBJECT_NULL) { 583*45748Smckusick /* 584*45748Smckusick * Nothing to copy 585*45748Smckusick */ 586*45748Smckusick *dst_object = VM_OBJECT_NULL; 587*45748Smckusick *dst_offset = 0; 588*45748Smckusick *src_needs_copy = FALSE; 589*45748Smckusick return; 590*45748Smckusick } 591*45748Smckusick 592*45748Smckusick /* 593*45748Smckusick * If the object's pager is null_pager or the 594*45748Smckusick * default pager, we don't have to make a copy 595*45748Smckusick * of it. Instead, we set the needs copy flag and 596*45748Smckusick * make a shadow later. 597*45748Smckusick */ 598*45748Smckusick 599*45748Smckusick vm_object_lock(src_object); 600*45748Smckusick if (src_object->pager == vm_pager_null || 601*45748Smckusick src_object->internal) { 602*45748Smckusick 603*45748Smckusick /* 604*45748Smckusick * Make another reference to the object 605*45748Smckusick */ 606*45748Smckusick src_object->ref_count++; 607*45748Smckusick 608*45748Smckusick /* 609*45748Smckusick * Mark all of the pages copy-on-write. 610*45748Smckusick */ 611*45748Smckusick for (p = (vm_page_t) queue_first(&src_object->memq); 612*45748Smckusick !queue_end(&src_object->memq, (queue_entry_t)p); 613*45748Smckusick p = (vm_page_t) queue_next(&p->listq)) { 614*45748Smckusick if (src_offset <= p->offset && 615*45748Smckusick p->offset < src_offset + size) 616*45748Smckusick p->copy_on_write = TRUE; 617*45748Smckusick } 618*45748Smckusick vm_object_unlock(src_object); 619*45748Smckusick 620*45748Smckusick *dst_object = src_object; 621*45748Smckusick *dst_offset = src_offset; 622*45748Smckusick 623*45748Smckusick /* 624*45748Smckusick * Must make a shadow when write is desired 625*45748Smckusick */ 626*45748Smckusick *src_needs_copy = TRUE; 627*45748Smckusick return; 628*45748Smckusick } 629*45748Smckusick 630*45748Smckusick /* 631*45748Smckusick * Try to collapse the object before copying it. 632*45748Smckusick */ 633*45748Smckusick vm_object_collapse(src_object); 634*45748Smckusick 635*45748Smckusick /* 636*45748Smckusick * If the object has a pager, the pager wants to 637*45748Smckusick * see all of the changes. We need a copy-object 638*45748Smckusick * for the changed pages. 639*45748Smckusick * 640*45748Smckusick * If there is a copy-object, and it is empty, 641*45748Smckusick * no changes have been made to the object since the 642*45748Smckusick * copy-object was made. We can use the same copy- 643*45748Smckusick * object. 644*45748Smckusick */ 645*45748Smckusick 646*45748Smckusick Retry1: 647*45748Smckusick old_copy = src_object->copy; 648*45748Smckusick if (old_copy != VM_OBJECT_NULL) { 649*45748Smckusick /* 650*45748Smckusick * Try to get the locks (out of order) 651*45748Smckusick */ 652*45748Smckusick if (!vm_object_lock_try(old_copy)) { 653*45748Smckusick vm_object_unlock(src_object); 654*45748Smckusick 655*45748Smckusick /* should spin a bit here... */ 656*45748Smckusick vm_object_lock(src_object); 657*45748Smckusick goto Retry1; 658*45748Smckusick } 659*45748Smckusick 660*45748Smckusick if (old_copy->resident_page_count == 0 && 661*45748Smckusick old_copy->pager == vm_pager_null) { 662*45748Smckusick /* 663*45748Smckusick * Return another reference to 664*45748Smckusick * the existing copy-object. 665*45748Smckusick */ 666*45748Smckusick old_copy->ref_count++; 667*45748Smckusick vm_object_unlock(old_copy); 668*45748Smckusick vm_object_unlock(src_object); 669*45748Smckusick *dst_object = old_copy; 670*45748Smckusick *dst_offset = src_offset; 671*45748Smckusick *src_needs_copy = FALSE; 672*45748Smckusick return; 673*45748Smckusick } 674*45748Smckusick vm_object_unlock(old_copy); 675*45748Smckusick } 676*45748Smckusick vm_object_unlock(src_object); 677*45748Smckusick 678*45748Smckusick /* 679*45748Smckusick * If the object has a pager, the pager wants 680*45748Smckusick * to see all of the changes. We must make 681*45748Smckusick * a copy-object and put the changed pages there. 682*45748Smckusick * 683*45748Smckusick * The copy-object is always made large enough to 684*45748Smckusick * completely shadow the original object, since 685*45748Smckusick * it may have several users who want to shadow 686*45748Smckusick * the original object at different points. 687*45748Smckusick */ 688*45748Smckusick 689*45748Smckusick new_copy = vm_object_allocate(src_object->size); 690*45748Smckusick 691*45748Smckusick Retry2: 692*45748Smckusick vm_object_lock(src_object); 693*45748Smckusick /* 694*45748Smckusick * Copy object may have changed while we were unlocked 695*45748Smckusick */ 696*45748Smckusick old_copy = src_object->copy; 697*45748Smckusick if (old_copy != VM_OBJECT_NULL) { 698*45748Smckusick /* 699*45748Smckusick * Try to get the locks (out of order) 700*45748Smckusick */ 701*45748Smckusick if (!vm_object_lock_try(old_copy)) { 702*45748Smckusick vm_object_unlock(src_object); 703*45748Smckusick goto Retry2; 704*45748Smckusick } 705*45748Smckusick 706*45748Smckusick /* 707*45748Smckusick * Consistency check 708*45748Smckusick */ 709*45748Smckusick if (old_copy->shadow != src_object || 710*45748Smckusick old_copy->shadow_offset != (vm_offset_t) 0) 711*45748Smckusick panic("vm_object_copy: copy/shadow inconsistency"); 712*45748Smckusick 713*45748Smckusick /* 714*45748Smckusick * Make the old copy-object shadow the new one. 715*45748Smckusick * It will receive no more pages from the original 716*45748Smckusick * object. 717*45748Smckusick */ 718*45748Smckusick 719*45748Smckusick src_object->ref_count--; /* remove ref. from old_copy */ 720*45748Smckusick old_copy->shadow = new_copy; 721*45748Smckusick new_copy->ref_count++; /* locking not needed - we 722*45748Smckusick have the only pointer */ 723*45748Smckusick vm_object_unlock(old_copy); /* done with old_copy */ 724*45748Smckusick } 725*45748Smckusick 726*45748Smckusick new_start = (vm_offset_t) 0; /* always shadow original at 0 */ 727*45748Smckusick new_end = (vm_offset_t) new_copy->size; /* for the whole object */ 728*45748Smckusick 729*45748Smckusick /* 730*45748Smckusick * Point the new copy at the existing object. 731*45748Smckusick */ 732*45748Smckusick 733*45748Smckusick new_copy->shadow = src_object; 734*45748Smckusick new_copy->shadow_offset = new_start; 735*45748Smckusick src_object->ref_count++; 736*45748Smckusick src_object->copy = new_copy; 737*45748Smckusick 738*45748Smckusick /* 739*45748Smckusick * Mark all the affected pages of the existing object 740*45748Smckusick * copy-on-write. 741*45748Smckusick */ 742*45748Smckusick p = (vm_page_t) queue_first(&src_object->memq); 743*45748Smckusick while (!queue_end(&src_object->memq, (queue_entry_t) p)) { 744*45748Smckusick if ((new_start <= p->offset) && (p->offset < new_end)) { 745*45748Smckusick p->copy_on_write = TRUE; 746*45748Smckusick } 747*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 748*45748Smckusick } 749*45748Smckusick 750*45748Smckusick vm_object_unlock(src_object); 751*45748Smckusick 752*45748Smckusick *dst_object = new_copy; 753*45748Smckusick *dst_offset = src_offset - new_start; 754*45748Smckusick *src_needs_copy = FALSE; 755*45748Smckusick } 756*45748Smckusick 757*45748Smckusick /* 758*45748Smckusick * vm_object_shadow: 759*45748Smckusick * 760*45748Smckusick * Create a new object which is backed by the 761*45748Smckusick * specified existing object range. The source 762*45748Smckusick * object reference is deallocated. 763*45748Smckusick * 764*45748Smckusick * The new object and offset into that object 765*45748Smckusick * are returned in the source parameters. 766*45748Smckusick */ 767*45748Smckusick 768*45748Smckusick void vm_object_shadow(object, offset, length) 769*45748Smckusick vm_object_t *object; /* IN/OUT */ 770*45748Smckusick vm_offset_t *offset; /* IN/OUT */ 771*45748Smckusick vm_size_t length; 772*45748Smckusick { 773*45748Smckusick register vm_object_t source; 774*45748Smckusick register vm_object_t result; 775*45748Smckusick 776*45748Smckusick source = *object; 777*45748Smckusick 778*45748Smckusick /* 779*45748Smckusick * Allocate a new object with the given length 780*45748Smckusick */ 781*45748Smckusick 782*45748Smckusick if ((result = vm_object_allocate(length)) == VM_OBJECT_NULL) 783*45748Smckusick panic("vm_object_shadow: no object for shadowing"); 784*45748Smckusick 785*45748Smckusick /* 786*45748Smckusick * The new object shadows the source object, adding 787*45748Smckusick * a reference to it. Our caller changes his reference 788*45748Smckusick * to point to the new object, removing a reference to 789*45748Smckusick * the source object. Net result: no change of reference 790*45748Smckusick * count. 791*45748Smckusick */ 792*45748Smckusick result->shadow = source; 793*45748Smckusick 794*45748Smckusick /* 795*45748Smckusick * Store the offset into the source object, 796*45748Smckusick * and fix up the offset into the new object. 797*45748Smckusick */ 798*45748Smckusick 799*45748Smckusick result->shadow_offset = *offset; 800*45748Smckusick 801*45748Smckusick /* 802*45748Smckusick * Return the new things 803*45748Smckusick */ 804*45748Smckusick 805*45748Smckusick *offset = 0; 806*45748Smckusick *object = result; 807*45748Smckusick } 808*45748Smckusick 809*45748Smckusick /* 810*45748Smckusick * Set the specified object's pager to the specified pager. 811*45748Smckusick */ 812*45748Smckusick 813*45748Smckusick void vm_object_setpager(object, pager, paging_offset, 814*45748Smckusick read_only) 815*45748Smckusick vm_object_t object; 816*45748Smckusick vm_pager_t pager; 817*45748Smckusick vm_offset_t paging_offset; 818*45748Smckusick boolean_t read_only; 819*45748Smckusick { 820*45748Smckusick #ifdef lint 821*45748Smckusick read_only++; /* No longer used */ 822*45748Smckusick #endif lint 823*45748Smckusick 824*45748Smckusick vm_object_lock(object); /* XXX ? */ 825*45748Smckusick object->pager = pager; 826*45748Smckusick object->paging_offset = paging_offset; 827*45748Smckusick vm_object_unlock(object); /* XXX ? */ 828*45748Smckusick } 829*45748Smckusick 830*45748Smckusick /* 831*45748Smckusick * vm_object_hash hashes the pager/id pair. 832*45748Smckusick */ 833*45748Smckusick 834*45748Smckusick #define vm_object_hash(pager) \ 835*45748Smckusick (((unsigned)pager)%VM_OBJECT_HASH_COUNT) 836*45748Smckusick 837*45748Smckusick /* 838*45748Smckusick * vm_object_lookup looks in the object cache for an object with the 839*45748Smckusick * specified pager and paging id. 840*45748Smckusick */ 841*45748Smckusick 842*45748Smckusick vm_object_t vm_object_lookup(pager) 843*45748Smckusick vm_pager_t pager; 844*45748Smckusick { 845*45748Smckusick register queue_t bucket; 846*45748Smckusick register vm_object_hash_entry_t entry; 847*45748Smckusick vm_object_t object; 848*45748Smckusick 849*45748Smckusick bucket = &vm_object_hashtable[vm_object_hash(pager)]; 850*45748Smckusick 851*45748Smckusick vm_object_cache_lock(); 852*45748Smckusick 853*45748Smckusick entry = (vm_object_hash_entry_t) queue_first(bucket); 854*45748Smckusick while (!queue_end(bucket, (queue_entry_t) entry)) { 855*45748Smckusick object = entry->object; 856*45748Smckusick if (object->pager == pager) { 857*45748Smckusick vm_object_lock(object); 858*45748Smckusick if (object->ref_count == 0) { 859*45748Smckusick queue_remove(&vm_object_cached_list, object, 860*45748Smckusick vm_object_t, cached_list); 861*45748Smckusick vm_object_cached--; 862*45748Smckusick } 863*45748Smckusick object->ref_count++; 864*45748Smckusick vm_object_unlock(object); 865*45748Smckusick vm_object_cache_unlock(); 866*45748Smckusick return(object); 867*45748Smckusick } 868*45748Smckusick entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links); 869*45748Smckusick } 870*45748Smckusick 871*45748Smckusick vm_object_cache_unlock(); 872*45748Smckusick return(VM_OBJECT_NULL); 873*45748Smckusick } 874*45748Smckusick 875*45748Smckusick /* 876*45748Smckusick * vm_object_enter enters the specified object/pager/id into 877*45748Smckusick * the hash table. 878*45748Smckusick */ 879*45748Smckusick 880*45748Smckusick void vm_object_enter(object, pager) 881*45748Smckusick vm_object_t object; 882*45748Smckusick vm_pager_t pager; 883*45748Smckusick { 884*45748Smckusick register queue_t bucket; 885*45748Smckusick register vm_object_hash_entry_t entry; 886*45748Smckusick 887*45748Smckusick /* 888*45748Smckusick * We don't cache null objects, and we can't cache 889*45748Smckusick * objects with the null pager. 890*45748Smckusick */ 891*45748Smckusick 892*45748Smckusick if (object == VM_OBJECT_NULL) 893*45748Smckusick return; 894*45748Smckusick if (pager == vm_pager_null) 895*45748Smckusick return; 896*45748Smckusick 897*45748Smckusick bucket = &vm_object_hashtable[vm_object_hash(pager)]; 898*45748Smckusick entry = (vm_object_hash_entry_t) 899*45748Smckusick malloc((u_long)sizeof *entry, M_VMOBJHASH, M_WAITOK); 900*45748Smckusick entry->object = object; 901*45748Smckusick object->can_persist = TRUE; 902*45748Smckusick 903*45748Smckusick vm_object_cache_lock(); 904*45748Smckusick queue_enter(bucket, entry, vm_object_hash_entry_t, hash_links); 905*45748Smckusick vm_object_cache_unlock(); 906*45748Smckusick } 907*45748Smckusick 908*45748Smckusick /* 909*45748Smckusick * vm_object_remove: 910*45748Smckusick * 911*45748Smckusick * Remove the pager from the hash table. 912*45748Smckusick * Note: This assumes that the object cache 913*45748Smckusick * is locked. XXX this should be fixed 914*45748Smckusick * by reorganizing vm_object_deallocate. 915*45748Smckusick */ 916*45748Smckusick vm_object_remove(pager) 917*45748Smckusick register vm_pager_t pager; 918*45748Smckusick { 919*45748Smckusick register queue_t bucket; 920*45748Smckusick register vm_object_hash_entry_t entry; 921*45748Smckusick register vm_object_t object; 922*45748Smckusick 923*45748Smckusick bucket = &vm_object_hashtable[vm_object_hash(pager)]; 924*45748Smckusick 925*45748Smckusick entry = (vm_object_hash_entry_t) queue_first(bucket); 926*45748Smckusick while (!queue_end(bucket, (queue_entry_t) entry)) { 927*45748Smckusick object = entry->object; 928*45748Smckusick if (object->pager == pager) { 929*45748Smckusick queue_remove(bucket, entry, vm_object_hash_entry_t, 930*45748Smckusick hash_links); 931*45748Smckusick free((caddr_t)entry, M_VMOBJHASH); 932*45748Smckusick break; 933*45748Smckusick } 934*45748Smckusick entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links); 935*45748Smckusick } 936*45748Smckusick } 937*45748Smckusick 938*45748Smckusick /* 939*45748Smckusick * vm_object_cache_clear removes all objects from the cache. 940*45748Smckusick * 941*45748Smckusick */ 942*45748Smckusick 943*45748Smckusick void vm_object_cache_clear() 944*45748Smckusick { 945*45748Smckusick register vm_object_t object; 946*45748Smckusick 947*45748Smckusick /* 948*45748Smckusick * Remove each object in the cache by scanning down the 949*45748Smckusick * list of cached objects. 950*45748Smckusick */ 951*45748Smckusick vm_object_cache_lock(); 952*45748Smckusick while (!queue_empty(&vm_object_cached_list)) { 953*45748Smckusick object = (vm_object_t) queue_first(&vm_object_cached_list); 954*45748Smckusick vm_object_cache_unlock(); 955*45748Smckusick 956*45748Smckusick /* 957*45748Smckusick * Note: it is important that we use vm_object_lookup 958*45748Smckusick * to gain a reference, and not vm_object_reference, because 959*45748Smckusick * the logic for removing an object from the cache lies in 960*45748Smckusick * lookup. 961*45748Smckusick */ 962*45748Smckusick if (object != vm_object_lookup(object->pager)) 963*45748Smckusick panic("vm_object_cache_clear: I'm sooo confused."); 964*45748Smckusick pager_cache(object, FALSE); 965*45748Smckusick 966*45748Smckusick vm_object_cache_lock(); 967*45748Smckusick } 968*45748Smckusick vm_object_cache_unlock(); 969*45748Smckusick } 970*45748Smckusick 971*45748Smckusick boolean_t vm_object_collapse_allowed = TRUE; 972*45748Smckusick /* 973*45748Smckusick * vm_object_collapse: 974*45748Smckusick * 975*45748Smckusick * Collapse an object with the object backing it. 976*45748Smckusick * Pages in the backing object are moved into the 977*45748Smckusick * parent, and the backing object is deallocated. 978*45748Smckusick * 979*45748Smckusick * Requires that the object be locked and the page 980*45748Smckusick * queues be unlocked. 981*45748Smckusick * 982*45748Smckusick */ 983*45748Smckusick void vm_object_collapse(object) 984*45748Smckusick register vm_object_t object; 985*45748Smckusick 986*45748Smckusick { 987*45748Smckusick register vm_object_t backing_object; 988*45748Smckusick register vm_offset_t backing_offset; 989*45748Smckusick register vm_size_t size; 990*45748Smckusick register vm_offset_t new_offset; 991*45748Smckusick register vm_page_t p, pp; 992*45748Smckusick 993*45748Smckusick if (!vm_object_collapse_allowed) 994*45748Smckusick return; 995*45748Smckusick 996*45748Smckusick while (TRUE) { 997*45748Smckusick /* 998*45748Smckusick * Verify that the conditions are right for collapse: 999*45748Smckusick * 1000*45748Smckusick * The object exists and no pages in it are currently 1001*45748Smckusick * being paged out (or have ever been paged out). 1002*45748Smckusick */ 1003*45748Smckusick if (object == VM_OBJECT_NULL || 1004*45748Smckusick object->paging_in_progress != 0 || 1005*45748Smckusick object->pager != vm_pager_null) 1006*45748Smckusick return; 1007*45748Smckusick 1008*45748Smckusick /* 1009*45748Smckusick * There is a backing object, and 1010*45748Smckusick */ 1011*45748Smckusick 1012*45748Smckusick if ((backing_object = object->shadow) == VM_OBJECT_NULL) 1013*45748Smckusick return; 1014*45748Smckusick 1015*45748Smckusick vm_object_lock(backing_object); 1016*45748Smckusick /* 1017*45748Smckusick * ... 1018*45748Smckusick * The backing object is not read_only, 1019*45748Smckusick * and no pages in the backing object are 1020*45748Smckusick * currently being paged out. 1021*45748Smckusick * The backing object is internal. 1022*45748Smckusick */ 1023*45748Smckusick 1024*45748Smckusick if (!backing_object->internal || 1025*45748Smckusick backing_object->paging_in_progress != 0) { 1026*45748Smckusick vm_object_unlock(backing_object); 1027*45748Smckusick return; 1028*45748Smckusick } 1029*45748Smckusick 1030*45748Smckusick /* 1031*45748Smckusick * The backing object can't be a copy-object: 1032*45748Smckusick * the shadow_offset for the copy-object must stay 1033*45748Smckusick * as 0. Furthermore (for the 'we have all the 1034*45748Smckusick * pages' case), if we bypass backing_object and 1035*45748Smckusick * just shadow the next object in the chain, old 1036*45748Smckusick * pages from that object would then have to be copied 1037*45748Smckusick * BOTH into the (former) backing_object and into the 1038*45748Smckusick * parent object. 1039*45748Smckusick */ 1040*45748Smckusick if (backing_object->shadow != VM_OBJECT_NULL && 1041*45748Smckusick backing_object->shadow->copy != VM_OBJECT_NULL) { 1042*45748Smckusick vm_object_unlock(backing_object); 1043*45748Smckusick return; 1044*45748Smckusick } 1045*45748Smckusick 1046*45748Smckusick /* 1047*45748Smckusick * We know that we can either collapse the backing 1048*45748Smckusick * object (if the parent is the only reference to 1049*45748Smckusick * it) or (perhaps) remove the parent's reference 1050*45748Smckusick * to it. 1051*45748Smckusick */ 1052*45748Smckusick 1053*45748Smckusick backing_offset = object->shadow_offset; 1054*45748Smckusick size = object->size; 1055*45748Smckusick 1056*45748Smckusick /* 1057*45748Smckusick * If there is exactly one reference to the backing 1058*45748Smckusick * object, we can collapse it into the parent. 1059*45748Smckusick */ 1060*45748Smckusick 1061*45748Smckusick if (backing_object->ref_count == 1) { 1062*45748Smckusick 1063*45748Smckusick /* 1064*45748Smckusick * We can collapse the backing object. 1065*45748Smckusick * 1066*45748Smckusick * Move all in-memory pages from backing_object 1067*45748Smckusick * to the parent. Pages that have been paged out 1068*45748Smckusick * will be overwritten by any of the parent's 1069*45748Smckusick * pages that shadow them. 1070*45748Smckusick */ 1071*45748Smckusick 1072*45748Smckusick while (!queue_empty(&backing_object->memq)) { 1073*45748Smckusick 1074*45748Smckusick p = (vm_page_t) 1075*45748Smckusick queue_first(&backing_object->memq); 1076*45748Smckusick 1077*45748Smckusick new_offset = (p->offset - backing_offset); 1078*45748Smckusick 1079*45748Smckusick /* 1080*45748Smckusick * If the parent has a page here, or if 1081*45748Smckusick * this page falls outside the parent, 1082*45748Smckusick * dispose of it. 1083*45748Smckusick * 1084*45748Smckusick * Otherwise, move it as planned. 1085*45748Smckusick */ 1086*45748Smckusick 1087*45748Smckusick if (p->offset < backing_offset || 1088*45748Smckusick new_offset >= size) { 1089*45748Smckusick vm_page_lock_queues(); 1090*45748Smckusick vm_page_free(p); 1091*45748Smckusick vm_page_unlock_queues(); 1092*45748Smckusick } else { 1093*45748Smckusick pp = vm_page_lookup(object, new_offset); 1094*45748Smckusick if (pp != VM_PAGE_NULL && !pp->fake) { 1095*45748Smckusick vm_page_lock_queues(); 1096*45748Smckusick vm_page_free(p); 1097*45748Smckusick vm_page_unlock_queues(); 1098*45748Smckusick } 1099*45748Smckusick else { 1100*45748Smckusick if (pp) { 1101*45748Smckusick /* may be someone waiting for it */ 1102*45748Smckusick PAGE_WAKEUP(pp); 1103*45748Smckusick vm_page_lock_queues(); 1104*45748Smckusick vm_page_free(pp); 1105*45748Smckusick vm_page_unlock_queues(); 1106*45748Smckusick } 1107*45748Smckusick vm_page_rename(p, object, new_offset); 1108*45748Smckusick } 1109*45748Smckusick } 1110*45748Smckusick } 1111*45748Smckusick 1112*45748Smckusick /* 1113*45748Smckusick * Move the pager from backing_object to object. 1114*45748Smckusick * 1115*45748Smckusick * XXX We're only using part of the paging space 1116*45748Smckusick * for keeps now... we ought to discard the 1117*45748Smckusick * unused portion. 1118*45748Smckusick */ 1119*45748Smckusick 1120*45748Smckusick object->pager = backing_object->pager; 1121*45748Smckusick object->paging_offset += backing_offset; 1122*45748Smckusick 1123*45748Smckusick backing_object->pager = vm_pager_null; 1124*45748Smckusick 1125*45748Smckusick /* 1126*45748Smckusick * Object now shadows whatever backing_object did. 1127*45748Smckusick * Note that the reference to backing_object->shadow 1128*45748Smckusick * moves from within backing_object to within object. 1129*45748Smckusick */ 1130*45748Smckusick 1131*45748Smckusick object->shadow = backing_object->shadow; 1132*45748Smckusick object->shadow_offset += backing_object->shadow_offset; 1133*45748Smckusick if (object->shadow != VM_OBJECT_NULL && 1134*45748Smckusick object->shadow->copy != VM_OBJECT_NULL) { 1135*45748Smckusick panic("vm_object_collapse: we collapsed a copy-object!"); 1136*45748Smckusick } 1137*45748Smckusick /* 1138*45748Smckusick * Discard backing_object. 1139*45748Smckusick * 1140*45748Smckusick * Since the backing object has no pages, no 1141*45748Smckusick * pager left, and no object references within it, 1142*45748Smckusick * all that is necessary is to dispose of it. 1143*45748Smckusick */ 1144*45748Smckusick 1145*45748Smckusick vm_object_unlock(backing_object); 1146*45748Smckusick 1147*45748Smckusick simple_lock(&vm_object_list_lock); 1148*45748Smckusick queue_remove(&vm_object_list, backing_object, 1149*45748Smckusick vm_object_t, object_list); 1150*45748Smckusick vm_object_count--; 1151*45748Smckusick simple_unlock(&vm_object_list_lock); 1152*45748Smckusick 1153*45748Smckusick free((caddr_t)backing_object, M_VMOBJ); 1154*45748Smckusick 1155*45748Smckusick object_collapses++; 1156*45748Smckusick } 1157*45748Smckusick else { 1158*45748Smckusick /* 1159*45748Smckusick * If all of the pages in the backing object are 1160*45748Smckusick * shadowed by the parent object, the parent 1161*45748Smckusick * object no longer has to shadow the backing 1162*45748Smckusick * object; it can shadow the next one in the 1163*45748Smckusick * chain. 1164*45748Smckusick * 1165*45748Smckusick * The backing object must not be paged out - we'd 1166*45748Smckusick * have to check all of the paged-out pages, as 1167*45748Smckusick * well. 1168*45748Smckusick */ 1169*45748Smckusick 1170*45748Smckusick if (backing_object->pager != vm_pager_null) { 1171*45748Smckusick vm_object_unlock(backing_object); 1172*45748Smckusick return; 1173*45748Smckusick } 1174*45748Smckusick 1175*45748Smckusick /* 1176*45748Smckusick * Should have a check for a 'small' number 1177*45748Smckusick * of pages here. 1178*45748Smckusick */ 1179*45748Smckusick 1180*45748Smckusick p = (vm_page_t) queue_first(&backing_object->memq); 1181*45748Smckusick while (!queue_end(&backing_object->memq, 1182*45748Smckusick (queue_entry_t) p)) { 1183*45748Smckusick 1184*45748Smckusick new_offset = (p->offset - backing_offset); 1185*45748Smckusick 1186*45748Smckusick /* 1187*45748Smckusick * If the parent has a page here, or if 1188*45748Smckusick * this page falls outside the parent, 1189*45748Smckusick * keep going. 1190*45748Smckusick * 1191*45748Smckusick * Otherwise, the backing_object must be 1192*45748Smckusick * left in the chain. 1193*45748Smckusick */ 1194*45748Smckusick 1195*45748Smckusick if (p->offset >= backing_offset && 1196*45748Smckusick new_offset <= size && 1197*45748Smckusick ((pp = vm_page_lookup(object, new_offset)) 1198*45748Smckusick == VM_PAGE_NULL || 1199*45748Smckusick pp->fake)) { 1200*45748Smckusick /* 1201*45748Smckusick * Page still needed. 1202*45748Smckusick * Can't go any further. 1203*45748Smckusick */ 1204*45748Smckusick vm_object_unlock(backing_object); 1205*45748Smckusick return; 1206*45748Smckusick } 1207*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 1208*45748Smckusick } 1209*45748Smckusick 1210*45748Smckusick /* 1211*45748Smckusick * Make the parent shadow the next object 1212*45748Smckusick * in the chain. Deallocating backing_object 1213*45748Smckusick * will not remove it, since its reference 1214*45748Smckusick * count is at least 2. 1215*45748Smckusick */ 1216*45748Smckusick 1217*45748Smckusick vm_object_reference(object->shadow = backing_object->shadow); 1218*45748Smckusick object->shadow_offset += backing_object->shadow_offset; 1219*45748Smckusick 1220*45748Smckusick /* Drop the reference count on backing_object. 1221*45748Smckusick * Since its ref_count was at least 2, it 1222*45748Smckusick * will not vanish; so we don't need to call 1223*45748Smckusick * vm_object_deallocate. 1224*45748Smckusick */ 1225*45748Smckusick backing_object->ref_count--; 1226*45748Smckusick vm_object_unlock(backing_object); 1227*45748Smckusick 1228*45748Smckusick object_bypasses ++; 1229*45748Smckusick 1230*45748Smckusick } 1231*45748Smckusick 1232*45748Smckusick /* 1233*45748Smckusick * Try again with this object's new backing object. 1234*45748Smckusick */ 1235*45748Smckusick } 1236*45748Smckusick } 1237*45748Smckusick 1238*45748Smckusick /* 1239*45748Smckusick * vm_object_page_remove: [internal] 1240*45748Smckusick * 1241*45748Smckusick * Removes all physical pages in the specified 1242*45748Smckusick * object range from the object's list of pages. 1243*45748Smckusick * 1244*45748Smckusick * The object must be locked. 1245*45748Smckusick */ 1246*45748Smckusick void vm_object_page_remove(object, start, end) 1247*45748Smckusick register vm_object_t object; 1248*45748Smckusick register vm_offset_t start; 1249*45748Smckusick register vm_offset_t end; 1250*45748Smckusick { 1251*45748Smckusick register vm_page_t p, next; 1252*45748Smckusick 1253*45748Smckusick if (object == VM_OBJECT_NULL) 1254*45748Smckusick return; 1255*45748Smckusick 1256*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 1257*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 1258*45748Smckusick next = (vm_page_t) queue_next(&p->listq); 1259*45748Smckusick if ((start <= p->offset) && (p->offset < end)) { 1260*45748Smckusick pmap_remove_all(VM_PAGE_TO_PHYS(p)); 1261*45748Smckusick vm_page_lock_queues(); 1262*45748Smckusick vm_page_free(p); 1263*45748Smckusick vm_page_unlock_queues(); 1264*45748Smckusick } 1265*45748Smckusick p = next; 1266*45748Smckusick } 1267*45748Smckusick } 1268*45748Smckusick 1269*45748Smckusick /* 1270*45748Smckusick * Routine: vm_object_coalesce 1271*45748Smckusick * Function: Coalesces two objects backing up adjoining 1272*45748Smckusick * regions of memory into a single object. 1273*45748Smckusick * 1274*45748Smckusick * returns TRUE if objects were combined. 1275*45748Smckusick * 1276*45748Smckusick * NOTE: Only works at the moment if the second object is NULL - 1277*45748Smckusick * if it's not, which object do we lock first? 1278*45748Smckusick * 1279*45748Smckusick * Parameters: 1280*45748Smckusick * prev_object First object to coalesce 1281*45748Smckusick * prev_offset Offset into prev_object 1282*45748Smckusick * next_object Second object into coalesce 1283*45748Smckusick * next_offset Offset into next_object 1284*45748Smckusick * 1285*45748Smckusick * prev_size Size of reference to prev_object 1286*45748Smckusick * next_size Size of reference to next_object 1287*45748Smckusick * 1288*45748Smckusick * Conditions: 1289*45748Smckusick * The object must *not* be locked. 1290*45748Smckusick */ 1291*45748Smckusick boolean_t vm_object_coalesce(prev_object, next_object, 1292*45748Smckusick prev_offset, next_offset, 1293*45748Smckusick prev_size, next_size) 1294*45748Smckusick 1295*45748Smckusick register vm_object_t prev_object; 1296*45748Smckusick vm_object_t next_object; 1297*45748Smckusick vm_offset_t prev_offset, next_offset; 1298*45748Smckusick vm_size_t prev_size, next_size; 1299*45748Smckusick { 1300*45748Smckusick vm_size_t newsize; 1301*45748Smckusick 1302*45748Smckusick #ifdef lint 1303*45748Smckusick next_offset++; 1304*45748Smckusick #endif lint 1305*45748Smckusick 1306*45748Smckusick if (next_object != VM_OBJECT_NULL) { 1307*45748Smckusick return(FALSE); 1308*45748Smckusick } 1309*45748Smckusick 1310*45748Smckusick if (prev_object == VM_OBJECT_NULL) { 1311*45748Smckusick return(TRUE); 1312*45748Smckusick } 1313*45748Smckusick 1314*45748Smckusick vm_object_lock(prev_object); 1315*45748Smckusick 1316*45748Smckusick /* 1317*45748Smckusick * Try to collapse the object first 1318*45748Smckusick */ 1319*45748Smckusick vm_object_collapse(prev_object); 1320*45748Smckusick 1321*45748Smckusick /* 1322*45748Smckusick * Can't coalesce if: 1323*45748Smckusick * . more than one reference 1324*45748Smckusick * . paged out 1325*45748Smckusick * . shadows another object 1326*45748Smckusick * . has a copy elsewhere 1327*45748Smckusick * (any of which mean that the pages not mapped to 1328*45748Smckusick * prev_entry may be in use anyway) 1329*45748Smckusick */ 1330*45748Smckusick 1331*45748Smckusick if (prev_object->ref_count > 1 || 1332*45748Smckusick prev_object->pager != vm_pager_null || 1333*45748Smckusick prev_object->shadow != VM_OBJECT_NULL || 1334*45748Smckusick prev_object->copy != VM_OBJECT_NULL) { 1335*45748Smckusick vm_object_unlock(prev_object); 1336*45748Smckusick return(FALSE); 1337*45748Smckusick } 1338*45748Smckusick 1339*45748Smckusick /* 1340*45748Smckusick * Remove any pages that may still be in the object from 1341*45748Smckusick * a previous deallocation. 1342*45748Smckusick */ 1343*45748Smckusick 1344*45748Smckusick vm_object_page_remove(prev_object, 1345*45748Smckusick prev_offset + prev_size, 1346*45748Smckusick prev_offset + prev_size + next_size); 1347*45748Smckusick 1348*45748Smckusick /* 1349*45748Smckusick * Extend the object if necessary. 1350*45748Smckusick */ 1351*45748Smckusick newsize = prev_offset + prev_size + next_size; 1352*45748Smckusick if (newsize > prev_object->size) 1353*45748Smckusick prev_object->size = newsize; 1354*45748Smckusick 1355*45748Smckusick vm_object_unlock(prev_object); 1356*45748Smckusick return(TRUE); 1357*45748Smckusick } 1358*45748Smckusick 1359*45748Smckusick /* 1360*45748Smckusick * vm_object_print: [ debug ] 1361*45748Smckusick */ 1362*45748Smckusick void vm_object_print(object, full) 1363*45748Smckusick vm_object_t object; 1364*45748Smckusick boolean_t full; 1365*45748Smckusick { 1366*45748Smckusick register vm_page_t p; 1367*45748Smckusick extern indent; 1368*45748Smckusick 1369*45748Smckusick register int count; 1370*45748Smckusick 1371*45748Smckusick if (object == VM_OBJECT_NULL) 1372*45748Smckusick return; 1373*45748Smckusick 1374*45748Smckusick iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ", 1375*45748Smckusick (int) object, (int) object->size, 1376*45748Smckusick object->resident_page_count, object->ref_count); 1377*45748Smckusick printf("pager=0x%x+0x%x, shadow=(0x%x)+0x%x\n", 1378*45748Smckusick (int) object->pager, (int) object->paging_offset, 1379*45748Smckusick (int) object->shadow, (int) object->shadow_offset); 1380*45748Smckusick printf("cache: next=0x%x, prev=0x%x\n", 1381*45748Smckusick object->cached_list.next, object->cached_list.prev); 1382*45748Smckusick 1383*45748Smckusick if (!full) 1384*45748Smckusick return; 1385*45748Smckusick 1386*45748Smckusick indent += 2; 1387*45748Smckusick count = 0; 1388*45748Smckusick p = (vm_page_t) queue_first(&object->memq); 1389*45748Smckusick while (!queue_end(&object->memq, (queue_entry_t) p)) { 1390*45748Smckusick if (count == 0) 1391*45748Smckusick iprintf("memory:="); 1392*45748Smckusick else if (count == 6) { 1393*45748Smckusick printf("\n"); 1394*45748Smckusick iprintf(" ..."); 1395*45748Smckusick count = 0; 1396*45748Smckusick } else 1397*45748Smckusick printf(","); 1398*45748Smckusick count++; 1399*45748Smckusick 1400*45748Smckusick printf("(off=0x%x,page=0x%x)", p->offset, VM_PAGE_TO_PHYS(p)); 1401*45748Smckusick p = (vm_page_t) queue_next(&p->listq); 1402*45748Smckusick } 1403*45748Smckusick if (count != 0) 1404*45748Smckusick printf("\n"); 1405*45748Smckusick indent -= 2; 1406*45748Smckusick } 1407