Annotation of Net2/vm/vm_object.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.