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

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();
1.1.1.2 ! root      457:                if (!p->busy)
        !           458:                        vm_page_deactivate(p);  /* optimisation from mach 3.0 -
        !           459:                                                 * [email protected],
        !           460:                                                 * Feb '93
        !           461:                                                 */
1.1       root      462:                vm_page_unlock_queues();
                    463:                p = next;
                    464:        }
                    465: }
                    466: 
                    467: /*
                    468:  *     Trim the object cache to size.
                    469:  */
                    470: vm_object_cache_trim()
                    471: {
                    472:        register vm_object_t    object;
                    473: 
                    474:        vm_object_cache_lock();
                    475:        while (vm_object_cached > vm_cache_max) {
                    476:                object = (vm_object_t) queue_first(&vm_object_cached_list);
                    477:                vm_object_cache_unlock();
                    478: 
                    479:                if (object != vm_object_lookup(object->pager))
                    480:                        panic("vm_object_deactivate: I'm sooo confused.");
                    481: 
                    482:                pager_cache(object, FALSE);
                    483: 
                    484:                vm_object_cache_lock();
                    485:        }
                    486:        vm_object_cache_unlock();
                    487: }
                    488: 
                    489: 
                    490: /*
                    491:  *     vm_object_shutdown()
                    492:  *
                    493:  *     Shut down the object system.  Unfortunately, while we
                    494:  *     may be trying to do this, init is happily waiting for
                    495:  *     processes to exit, and therefore will be causing some objects
                    496:  *     to be deallocated.  To handle this, we gain a fake reference
                    497:  *     to all objects we release paging areas for.  This will prevent
                    498:  *     a duplicate deallocation.  This routine is probably full of
                    499:  *     race conditions!
                    500:  */
                    501: 
                    502: void vm_object_shutdown()
                    503: {
                    504:        register vm_object_t    object;
                    505: 
                    506:        /*
                    507:         *      Clean up the object cache *before* we screw up the reference
                    508:         *      counts on all of the objects.
                    509:         */
                    510: 
                    511:        vm_object_cache_clear();
                    512: 
                    513:        printf("free paging spaces: ");
                    514: 
                    515:        /*
                    516:         *      First we gain a reference to each object so that
                    517:         *      no one else will deallocate them.
                    518:         */
                    519: 
                    520:        simple_lock(&vm_object_list_lock);
                    521:        object = (vm_object_t) queue_first(&vm_object_list);
                    522:        while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
                    523:                vm_object_reference(object);
                    524:                object = (vm_object_t) queue_next(&object->object_list);
                    525:        }
                    526:        simple_unlock(&vm_object_list_lock);
                    527: 
                    528:        /*
                    529:         *      Now we deallocate all the paging areas.  We don't need
                    530:         *      to lock anything because we've reduced to a single
                    531:         *      processor while shutting down.  This also assumes that
                    532:         *      no new objects are being created.
                    533:         */
                    534: 
                    535:        object = (vm_object_t) queue_first(&vm_object_list);
                    536:        while (!queue_end(&vm_object_list, (queue_entry_t) object)) {
                    537:                if (object->pager != NULL)
                    538:                        vm_pager_deallocate(object->pager);
                    539:                object = (vm_object_t) queue_next(&object->object_list);
                    540:                printf(".");
                    541:        }
                    542:        printf("done.\n");
                    543: }
                    544: 
                    545: /*
                    546:  *     vm_object_pmap_copy:
                    547:  *
                    548:  *     Makes all physical pages in the specified
                    549:  *     object range copy-on-write.  No writeable
                    550:  *     references to these pages should remain.
                    551:  *
                    552:  *     The object must *not* be locked.
                    553:  */
                    554: void vm_object_pmap_copy(object, start, end)
                    555:        register vm_object_t    object;
                    556:        register vm_offset_t    start;
                    557:        register vm_offset_t    end;
                    558: {
                    559:        register vm_page_t      p;
                    560: 
                    561:        if (object == NULL)
                    562:                return;
                    563: 
                    564:        vm_object_lock(object);
                    565:        p = (vm_page_t) queue_first(&object->memq);
                    566:        while (!queue_end(&object->memq, (queue_entry_t) p)) {
                    567:                if ((start <= p->offset) && (p->offset < end)) {
                    568:                        pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_READ);
                    569:                        p->copy_on_write = TRUE;
                    570:                }
                    571:                p = (vm_page_t) queue_next(&p->listq);
                    572:        }
                    573:        vm_object_unlock(object);
                    574: }
                    575: 
                    576: /*
                    577:  *     vm_object_pmap_remove:
                    578:  *
                    579:  *     Removes all physical pages in the specified
                    580:  *     object range from all physical maps.
                    581:  *
                    582:  *     The object must *not* be locked.
                    583:  */
                    584: void vm_object_pmap_remove(object, start, end)
                    585:        register vm_object_t    object;
                    586:        register vm_offset_t    start;
                    587:        register vm_offset_t    end;
                    588: {
                    589:        register vm_page_t      p;
                    590: 
                    591:        if (object == NULL)
                    592:                return;
                    593: 
                    594:        vm_object_lock(object);
                    595:        p = (vm_page_t) queue_first(&object->memq);
                    596:        while (!queue_end(&object->memq, (queue_entry_t) p)) {
                    597:                if ((start <= p->offset) && (p->offset < end))
                    598:                        pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
                    599:                p = (vm_page_t) queue_next(&p->listq);
                    600:        }
                    601:        vm_object_unlock(object);
                    602: }
                    603: 
                    604: /*
                    605:  *     vm_object_copy:
                    606:  *
                    607:  *     Create a new object which is a copy of an existing
                    608:  *     object, and mark all of the pages in the existing
                    609:  *     object 'copy-on-write'.  The new object has one reference.
                    610:  *     Returns the new object.
                    611:  *
                    612:  *     May defer the copy until later if the object is not backed
                    613:  *     up by a non-default pager.
                    614:  */
                    615: void vm_object_copy(src_object, src_offset, size,
                    616:                    dst_object, dst_offset, src_needs_copy)
                    617:        register vm_object_t    src_object;
                    618:        vm_offset_t             src_offset;
                    619:        vm_size_t               size;
                    620:        vm_object_t             *dst_object;    /* OUT */
                    621:        vm_offset_t             *dst_offset;    /* OUT */
                    622:        boolean_t               *src_needs_copy;        /* OUT */
                    623: {
                    624:        register vm_object_t    new_copy;
                    625:        register vm_object_t    old_copy;
                    626:        vm_offset_t             new_start, new_end;
                    627: 
                    628:        register vm_page_t      p;
                    629: 
                    630:        if (src_object == NULL) {
                    631:                /*
                    632:                 *      Nothing to copy
                    633:                 */
                    634:                *dst_object = NULL;
                    635:                *dst_offset = 0;
                    636:                *src_needs_copy = FALSE;
                    637:                return;
                    638:        }
                    639: 
                    640:        /*
                    641:         *      If the object's pager is null_pager or the
                    642:         *      default pager, we don't have to make a copy
                    643:         *      of it.  Instead, we set the needs copy flag and
                    644:         *      make a shadow later.
                    645:         */
                    646: 
                    647:        vm_object_lock(src_object);
                    648:        if (src_object->pager == NULL ||
                    649:            src_object->internal) {
                    650: 
                    651:                /*
                    652:                 *      Make another reference to the object
                    653:                 */
                    654:                src_object->ref_count++;
                    655: 
                    656:                /*
                    657:                 *      Mark all of the pages copy-on-write.
                    658:                 */
                    659:                for (p = (vm_page_t) queue_first(&src_object->memq);
                    660:                     !queue_end(&src_object->memq, (queue_entry_t)p);
                    661:                     p = (vm_page_t) queue_next(&p->listq)) {
                    662:                        if (src_offset <= p->offset &&
                    663:                            p->offset < src_offset + size)
                    664:                                p->copy_on_write = TRUE;
                    665:                }
                    666:                vm_object_unlock(src_object);
                    667: 
                    668:                *dst_object = src_object;
                    669:                *dst_offset = src_offset;
                    670:                
                    671:                /*
                    672:                 *      Must make a shadow when write is desired
                    673:                 */
                    674:                *src_needs_copy = TRUE;
                    675:                return;
                    676:        }
                    677: 
                    678:        /*
                    679:         *      Try to collapse the object before copying it.
                    680:         */
                    681:        vm_object_collapse(src_object);
                    682: 
                    683:        /*
                    684:         *      If the object has a pager, the pager wants to
                    685:         *      see all of the changes.  We need a copy-object
                    686:         *      for the changed pages.
                    687:         *
                    688:         *      If there is a copy-object, and it is empty,
                    689:         *      no changes have been made to the object since the
                    690:         *      copy-object was made.  We can use the same copy-
                    691:         *      object.
                    692:         */
                    693: 
                    694:     Retry1:
                    695:        old_copy = src_object->copy;
                    696:        if (old_copy != NULL) {
                    697:                /*
                    698:                 *      Try to get the locks (out of order)
                    699:                 */
                    700:                if (!vm_object_lock_try(old_copy)) {
                    701:                        vm_object_unlock(src_object);
                    702: 
                    703:                        /* should spin a bit here... */
                    704:                        vm_object_lock(src_object);
                    705:                        goto Retry1;
                    706:                }
                    707: 
                    708:                if (old_copy->resident_page_count == 0 &&
                    709:                    old_copy->pager == NULL) {
                    710:                        /*
                    711:                         *      Return another reference to
                    712:                         *      the existing copy-object.
                    713:                         */
                    714:                        old_copy->ref_count++;
                    715:                        vm_object_unlock(old_copy);
                    716:                        vm_object_unlock(src_object);
                    717:                        *dst_object = old_copy;
                    718:                        *dst_offset = src_offset;
                    719:                        *src_needs_copy = FALSE;
                    720:                        return;
                    721:                }
                    722:                vm_object_unlock(old_copy);
                    723:        }
                    724:        vm_object_unlock(src_object);
                    725: 
                    726:        /*
                    727:         *      If the object has a pager, the pager wants
                    728:         *      to see all of the changes.  We must make
                    729:         *      a copy-object and put the changed pages there.
                    730:         *
                    731:         *      The copy-object is always made large enough to
                    732:         *      completely shadow the original object, since
                    733:         *      it may have several users who want to shadow
                    734:         *      the original object at different points.
                    735:         */
                    736: 
                    737:        new_copy = vm_object_allocate(src_object->size);
                    738: 
                    739:     Retry2:
                    740:        vm_object_lock(src_object);
                    741:        /*
                    742:         *      Copy object may have changed while we were unlocked
                    743:         */
                    744:        old_copy = src_object->copy;
                    745:        if (old_copy != NULL) {
                    746:                /*
                    747:                 *      Try to get the locks (out of order)
                    748:                 */
                    749:                if (!vm_object_lock_try(old_copy)) {
                    750:                        vm_object_unlock(src_object);
                    751:                        goto Retry2;
                    752:                }
                    753: 
                    754:                /*
                    755:                 *      Consistency check
                    756:                 */
                    757:                if (old_copy->shadow != src_object ||
                    758:                    old_copy->shadow_offset != (vm_offset_t) 0)
                    759:                        panic("vm_object_copy: copy/shadow inconsistency");
                    760: 
                    761:                /*
                    762:                 *      Make the old copy-object shadow the new one.
                    763:                 *      It will receive no more pages from the original
                    764:                 *      object.
                    765:                 */
                    766: 
                    767:                src_object->ref_count--;        /* remove ref. from old_copy */
                    768:                old_copy->shadow = new_copy;
                    769:                new_copy->ref_count++;          /* locking not needed - we
                    770:                                                   have the only pointer */
                    771:                vm_object_unlock(old_copy);     /* done with old_copy */
                    772:        }
                    773: 
                    774:        new_start = (vm_offset_t) 0;    /* always shadow original at 0 */
                    775:        new_end   = (vm_offset_t) new_copy->size; /* for the whole object */
                    776: 
                    777:        /*
                    778:         *      Point the new copy at the existing object.
                    779:         */
                    780: 
                    781:        new_copy->shadow = src_object;
                    782:        new_copy->shadow_offset = new_start;
                    783:        src_object->ref_count++;
                    784:        src_object->copy = new_copy;
                    785: 
                    786:        /*
                    787:         *      Mark all the affected pages of the existing object
                    788:         *      copy-on-write.
                    789:         */
                    790:        p = (vm_page_t) queue_first(&src_object->memq);
                    791:        while (!queue_end(&src_object->memq, (queue_entry_t) p)) {
                    792:                if ((new_start <= p->offset) && (p->offset < new_end))
                    793:                        p->copy_on_write = TRUE;
                    794:                p = (vm_page_t) queue_next(&p->listq);
                    795:        }
                    796: 
                    797:        vm_object_unlock(src_object);
                    798: 
                    799:        *dst_object = new_copy;
                    800:        *dst_offset = src_offset - new_start;
                    801:        *src_needs_copy = FALSE;
                    802: }
                    803: 
                    804: /*
                    805:  *     vm_object_shadow:
                    806:  *
                    807:  *     Create a new object which is backed by the
                    808:  *     specified existing object range.  The source
                    809:  *     object reference is deallocated.
                    810:  *
                    811:  *     The new object and offset into that object
                    812:  *     are returned in the source parameters.
                    813:  */
                    814: 
                    815: void vm_object_shadow(object, offset, length)
                    816:        vm_object_t     *object;        /* IN/OUT */
                    817:        vm_offset_t     *offset;        /* IN/OUT */
                    818:        vm_size_t       length;
                    819: {
                    820:        register vm_object_t    source;
                    821:        register vm_object_t    result;
                    822: 
                    823:        source = *object;
                    824: 
                    825:        /*
                    826:         *      Allocate a new object with the given length
                    827:         */
                    828: 
                    829:        if ((result = vm_object_allocate(length)) == NULL)
                    830:                panic("vm_object_shadow: no object for shadowing");
                    831: 
                    832:        /*
                    833:         *      The new object shadows the source object, adding
                    834:         *      a reference to it.  Our caller changes his reference
                    835:         *      to point to the new object, removing a reference to
                    836:         *      the source object.  Net result: no change of reference
                    837:         *      count.
                    838:         */
                    839:        result->shadow = source;
                    840:        
                    841:        /*
                    842:         *      Store the offset into the source object,
                    843:         *      and fix up the offset into the new object.
                    844:         */
                    845: 
                    846:        result->shadow_offset = *offset;
                    847: 
                    848:        /*
                    849:         *      Return the new things
                    850:         */
                    851: 
                    852:        *offset = 0;
                    853:        *object = result;
                    854: }
                    855: 
                    856: /*
                    857:  *     Set the specified object's pager to the specified pager.
                    858:  */
                    859: 
                    860: void vm_object_setpager(object, pager, paging_offset,
                    861:                        read_only)
                    862:        vm_object_t     object;
                    863:        vm_pager_t      pager;
                    864:        vm_offset_t     paging_offset;
                    865:        boolean_t       read_only;
                    866: {
                    867: #ifdef lint
                    868:        read_only++;    /* No longer used */
                    869: #endif lint
                    870: 
                    871:        vm_object_lock(object);                 /* XXX ? */
                    872:        object->pager = pager;
                    873:        object->paging_offset = paging_offset;
                    874:        vm_object_unlock(object);                       /* XXX ? */
                    875: }
                    876: 
                    877: /*
                    878:  *     vm_object_hash hashes the pager/id pair.
                    879:  */
                    880: 
                    881: #define vm_object_hash(pager) \
                    882:        (((unsigned)pager)%VM_OBJECT_HASH_COUNT)
                    883: 
                    884: /*
                    885:  *     vm_object_lookup looks in the object cache for an object with the
                    886:  *     specified pager and paging id.
                    887:  */
                    888: 
                    889: vm_object_t vm_object_lookup(pager)
                    890:        vm_pager_t      pager;
                    891: {
                    892:        register queue_t                bucket;
                    893:        register vm_object_hash_entry_t entry;
                    894:        vm_object_t                     object;
                    895: 
                    896:        bucket = &vm_object_hashtable[vm_object_hash(pager)];
                    897: 
                    898:        vm_object_cache_lock();
                    899: 
                    900:        entry = (vm_object_hash_entry_t) queue_first(bucket);
                    901:        while (!queue_end(bucket, (queue_entry_t) entry)) {
                    902:                object = entry->object;
                    903:                if (object->pager == pager) {
                    904:                        vm_object_lock(object);
                    905:                        if (object->ref_count == 0) {
                    906:                                queue_remove(&vm_object_cached_list, object,
                    907:                                                vm_object_t, cached_list);
                    908:                                vm_object_cached--;
                    909:                        }
                    910:                        object->ref_count++;
                    911:                        vm_object_unlock(object);
                    912:                        vm_object_cache_unlock();
                    913:                        return(object);
                    914:                }
                    915:                entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
                    916:        }
                    917: 
                    918:        vm_object_cache_unlock();
                    919:        return(NULL);
                    920: }
                    921: 
                    922: /*
                    923:  *     vm_object_enter enters the specified object/pager/id into
                    924:  *     the hash table.
                    925:  */
                    926: 
                    927: void vm_object_enter(object, pager)
                    928:        vm_object_t     object;
                    929:        vm_pager_t      pager;
                    930: {
                    931:        register queue_t                bucket;
                    932:        register vm_object_hash_entry_t entry;
                    933: 
                    934:        /*
                    935:         *      We don't cache null objects, and we can't cache
                    936:         *      objects with the null pager.
                    937:         */
                    938: 
                    939:        if (object == NULL)
                    940:                return;
                    941:        if (pager == NULL)
                    942:                return;
                    943: 
                    944:        bucket = &vm_object_hashtable[vm_object_hash(pager)];
                    945:        entry = (vm_object_hash_entry_t)
                    946:                malloc((u_long)sizeof *entry, M_VMOBJHASH, M_WAITOK);
                    947:        entry->object = object;
                    948:        object->can_persist = TRUE;
                    949: 
                    950:        vm_object_cache_lock();
                    951:        queue_enter(bucket, entry, vm_object_hash_entry_t, hash_links);
                    952:        vm_object_cache_unlock();
                    953: }
                    954: 
                    955: /*
                    956:  *     vm_object_remove:
                    957:  *
                    958:  *     Remove the pager from the hash table.
                    959:  *     Note:  This assumes that the object cache
                    960:  *     is locked.  XXX this should be fixed
                    961:  *     by reorganizing vm_object_deallocate.
                    962:  */
                    963: vm_object_remove(pager)
                    964:        register vm_pager_t     pager;
                    965: {
                    966:        register queue_t                bucket;
                    967:        register vm_object_hash_entry_t entry;
                    968:        register vm_object_t            object;
                    969: 
                    970:        bucket = &vm_object_hashtable[vm_object_hash(pager)];
                    971: 
                    972:        entry = (vm_object_hash_entry_t) queue_first(bucket);
                    973:        while (!queue_end(bucket, (queue_entry_t) entry)) {
                    974:                object = entry->object;
                    975:                if (object->pager == pager) {
                    976:                        queue_remove(bucket, entry, vm_object_hash_entry_t,
                    977:                                        hash_links);
                    978:                        free((caddr_t)entry, M_VMOBJHASH);
                    979:                        break;
                    980:                }
                    981:                entry = (vm_object_hash_entry_t) queue_next(&entry->hash_links);
                    982:        }
                    983: }
                    984: 
                    985: /*
                    986:  *     vm_object_cache_clear removes all objects from the cache.
                    987:  *
                    988:  */
                    989: 
                    990: void vm_object_cache_clear()
                    991: {
                    992:        register vm_object_t    object;
                    993: 
                    994:        /*
                    995:         *      Remove each object in the cache by scanning down the
                    996:         *      list of cached objects.
                    997:         */
                    998:        vm_object_cache_lock();
                    999:        while (!queue_empty(&vm_object_cached_list)) {
                   1000:                object = (vm_object_t) queue_first(&vm_object_cached_list);
                   1001:                vm_object_cache_unlock();
                   1002: 
                   1003:                /* 
                   1004:                 * Note: it is important that we use vm_object_lookup
                   1005:                 * to gain a reference, and not vm_object_reference, because
                   1006:                 * the logic for removing an object from the cache lies in 
                   1007:                 * lookup.
                   1008:                 */
                   1009:                if (object != vm_object_lookup(object->pager))
                   1010:                        panic("vm_object_cache_clear: I'm sooo confused.");
                   1011:                pager_cache(object, FALSE);
                   1012: 
                   1013:                vm_object_cache_lock();
                   1014:        }
                   1015:        vm_object_cache_unlock();
                   1016: }
                   1017: 
                   1018: boolean_t      vm_object_collapse_allowed = TRUE;
                   1019: /*
                   1020:  *     vm_object_collapse:
                   1021:  *
                   1022:  *     Collapse an object with the object backing it.
                   1023:  *     Pages in the backing object are moved into the
                   1024:  *     parent, and the backing object is deallocated.
                   1025:  *
                   1026:  *     Requires that the object be locked and the page
                   1027:  *     queues be unlocked.
                   1028:  *
                   1029:  */
                   1030: void vm_object_collapse(object)
                   1031:        register vm_object_t    object;
                   1032: 
                   1033: {
                   1034:        register vm_object_t    backing_object;
                   1035:        register vm_offset_t    backing_offset;
                   1036:        register vm_size_t      size;
                   1037:        register vm_offset_t    new_offset;
                   1038:        register vm_page_t      p, pp;
                   1039: 
                   1040:        if (!vm_object_collapse_allowed)
                   1041:                return;
                   1042: 
                   1043:        while (TRUE) {
                   1044:                /*
                   1045:                 *      Verify that the conditions are right for collapse:
                   1046:                 *
                   1047:                 *      The object exists and no pages in it are currently
                   1048:                 *      being paged out (or have ever been paged out).
                   1049:                 */
                   1050:                if (object == NULL ||
                   1051:                    object->paging_in_progress != 0 ||
                   1052:                    object->pager != NULL)
                   1053:                        return;
                   1054: 
                   1055:                /*
                   1056:                 *              There is a backing object, and
                   1057:                 */
                   1058:        
                   1059:                if ((backing_object = object->shadow) == NULL)
                   1060:                        return;
                   1061:        
                   1062:                vm_object_lock(backing_object);
                   1063:                /*
                   1064:                 *      ...
                   1065:                 *              The backing object is not read_only,
                   1066:                 *              and no pages in the backing object are
                   1067:                 *              currently being paged out.
                   1068:                 *              The backing object is internal.
                   1069:                 */
                   1070:        
                   1071:                if (!backing_object->internal ||
                   1072:                    backing_object->paging_in_progress != 0) {
                   1073:                        vm_object_unlock(backing_object);
                   1074:                        return;
                   1075:                }
                   1076:        
                   1077:                /*
                   1078:                 *      The backing object can't be a copy-object:
                   1079:                 *      the shadow_offset for the copy-object must stay
                   1080:                 *      as 0.  Furthermore (for the 'we have all the
                   1081:                 *      pages' case), if we bypass backing_object and
                   1082:                 *      just shadow the next object in the chain, old
                   1083:                 *      pages from that object would then have to be copied
                   1084:                 *      BOTH into the (former) backing_object and into the
                   1085:                 *      parent object.
                   1086:                 */
                   1087:                if (backing_object->shadow != NULL &&
                   1088:                    backing_object->shadow->copy != NULL) {
                   1089:                        vm_object_unlock(backing_object);
                   1090:                        return;
                   1091:                }
                   1092: 
                   1093:                /*
                   1094:                 *      We know that we can either collapse the backing
                   1095:                 *      object (if the parent is the only reference to
                   1096:                 *      it) or (perhaps) remove the parent's reference
                   1097:                 *      to it.
                   1098:                 */
                   1099: 
                   1100:                backing_offset = object->shadow_offset;
                   1101:                size = object->size;
                   1102: 
                   1103:                /*
                   1104:                 *      If there is exactly one reference to the backing
                   1105:                 *      object, we can collapse it into the parent.
                   1106:                 */
                   1107:        
                   1108:                if (backing_object->ref_count == 1) {
                   1109: 
                   1110:                        /*
                   1111:                         *      We can collapse the backing object.
                   1112:                         *
                   1113:                         *      Move all in-memory pages from backing_object
                   1114:                         *      to the parent.  Pages that have been paged out
                   1115:                         *      will be overwritten by any of the parent's
                   1116:                         *      pages that shadow them.
                   1117:                         */
                   1118: 
                   1119:                        while (!queue_empty(&backing_object->memq)) {
                   1120: 
                   1121:                                p = (vm_page_t)
                   1122:                                        queue_first(&backing_object->memq);
                   1123: 
                   1124:                                new_offset = (p->offset - backing_offset);
                   1125: 
                   1126:                                /*
                   1127:                                 *      If the parent has a page here, or if
                   1128:                                 *      this page falls outside the parent,
                   1129:                                 *      dispose of it.
                   1130:                                 *
                   1131:                                 *      Otherwise, move it as planned.
                   1132:                                 */
                   1133: 
                   1134:                                if (p->offset < backing_offset ||
                   1135:                                    new_offset >= size) {
                   1136:                                        vm_page_lock_queues();
                   1137:                                        vm_page_free(p);
                   1138:                                        vm_page_unlock_queues();
                   1139:                                } else {
                   1140:                                    pp = vm_page_lookup(object, new_offset);
                   1141:                                    if (pp != NULL && !pp->fake) {
                   1142:                                        vm_page_lock_queues();
                   1143:                                        vm_page_free(p);
                   1144:                                        vm_page_unlock_queues();
                   1145:                                    }
                   1146:                                    else {
                   1147:                                        if (pp) {
1.1.1.2 ! root     1148: #if 1
        !          1149:                                            /*
        !          1150:                                             *  This should never happen -- the
        !          1151:                                             *  parent cannot have ever had an
        !          1152:                                             *  external memory object, and thus
        !          1153:                                             *  cannot have absent pages.
        !          1154:                                             */
        !          1155:                                            panic("vm_object_collapse: bad case");
        !          1156:                                            /* [email protected] - from
        !          1157:                                               mach 3.0 VM */
        !          1158: #else
1.1       root     1159:                                            /* may be someone waiting for it */
                   1160:                                            PAGE_WAKEUP(pp);
                   1161:                                            vm_page_lock_queues();
                   1162:                                            vm_page_free(pp);
                   1163:                                            vm_page_unlock_queues();
1.1.1.2 ! root     1164: #endif
1.1       root     1165:                                        }
1.1.1.2 ! root     1166:                                        /*
        !          1167:                                         *      Parent now has no page.
        !          1168:                                         *      Move the backing object's page
        !          1169:                                         *      up.
        !          1170:                                         */
1.1       root     1171:                                        vm_page_rename(p, object, new_offset);
                   1172:                                    }
                   1173:                                }
                   1174:                        }
                   1175: 
                   1176:                        /*
                   1177:                         *      Move the pager from backing_object to object.
                   1178:                         *
                   1179:                         *      XXX We're only using part of the paging space
                   1180:                         *      for keeps now... we ought to discard the
                   1181:                         *      unused portion.
                   1182:                         */
                   1183: 
                   1184:                        object->pager = backing_object->pager;
1.1.1.2 ! root     1185: #if 1
        !          1186:                        /* Mach 3.0 code */
        !          1187:                        /* [email protected], 12 Feb 1993 */
        !          1188: 
        !          1189:                        /*
        !          1190:                         * If there is no pager, leave paging-offset alone.
        !          1191:                         */
        !          1192:                        if (object->pager)
        !          1193:                                object->paging_offset =
        !          1194:                                        backing_object->paging_offset +
        !          1195:                                                backing_offset;
        !          1196: #else
        !          1197:                        /* old VM 2.5 version */
1.1       root     1198:                        object->paging_offset += backing_offset;
1.1.1.2 ! root     1199: #endif
1.1       root     1200: 
                   1201:                        backing_object->pager = NULL;
                   1202: 
                   1203:                        /*
                   1204:                         *      Object now shadows whatever backing_object did.
                   1205:                         *      Note that the reference to backing_object->shadow
                   1206:                         *      moves from within backing_object to within object.
                   1207:                         */
                   1208: 
                   1209:                        object->shadow = backing_object->shadow;
                   1210:                        object->shadow_offset += backing_object->shadow_offset;
                   1211:                        if (object->shadow != NULL &&
                   1212:                            object->shadow->copy != NULL) {
                   1213:                                panic("vm_object_collapse: we collapsed a copy-object!");
                   1214:                        }
                   1215:                        /*
                   1216:                         *      Discard backing_object.
                   1217:                         *
                   1218:                         *      Since the backing object has no pages, no
                   1219:                         *      pager left, and no object references within it,
                   1220:                         *      all that is necessary is to dispose of it.
                   1221:                         */
                   1222: 
                   1223:                        vm_object_unlock(backing_object);
                   1224: 
                   1225:                        simple_lock(&vm_object_list_lock);
                   1226:                        queue_remove(&vm_object_list, backing_object,
                   1227:                                                vm_object_t, object_list);
                   1228:                        vm_object_count--;
                   1229:                        simple_unlock(&vm_object_list_lock);
                   1230: 
                   1231:                        free((caddr_t)backing_object, M_VMOBJ);
                   1232: 
                   1233:                        object_collapses++;
                   1234:                }
                   1235:                else {
                   1236:                        /*
                   1237:                         *      If all of the pages in the backing object are
                   1238:                         *      shadowed by the parent object, the parent
                   1239:                         *      object no longer has to shadow the backing
                   1240:                         *      object; it can shadow the next one in the
                   1241:                         *      chain.
                   1242:                         *
                   1243:                         *      The backing object must not be paged out - we'd
                   1244:                         *      have to check all of the paged-out pages, as
                   1245:                         *      well.
                   1246:                         */
                   1247: 
                   1248:                        if (backing_object->pager != NULL) {
                   1249:                                vm_object_unlock(backing_object);
                   1250:                                return;
                   1251:                        }
                   1252: 
                   1253:                        /*
                   1254:                         *      Should have a check for a 'small' number
                   1255:                         *      of pages here.
                   1256:                         */
                   1257: 
                   1258:                        p = (vm_page_t) queue_first(&backing_object->memq);
                   1259:                        while (!queue_end(&backing_object->memq,
                   1260:                                          (queue_entry_t) p)) {
                   1261: 
                   1262:                                new_offset = (p->offset - backing_offset);
                   1263: 
                   1264:                                /*
                   1265:                                 *      If the parent has a page here, or if
                   1266:                                 *      this page falls outside the parent,
                   1267:                                 *      keep going.
                   1268:                                 *
                   1269:                                 *      Otherwise, the backing_object must be
                   1270:                                 *      left in the chain.
                   1271:                                 */
                   1272: 
                   1273:                                if (p->offset >= backing_offset &&
                   1274:                                    new_offset <= size &&
                   1275:                                    ((pp = vm_page_lookup(object, new_offset))
                   1276:                                      == NULL ||
                   1277:                                     pp->fake)) {
                   1278:                                        /*
                   1279:                                         *      Page still needed.
                   1280:                                         *      Can't go any further.
                   1281:                                         */
                   1282:                                        vm_object_unlock(backing_object);
                   1283:                                        return;
                   1284:                                }
                   1285:                                p = (vm_page_t) queue_next(&p->listq);
                   1286:                        }
                   1287: 
                   1288:                        /*
                   1289:                         *      Make the parent shadow the next object
                   1290:                         *      in the chain.  Deallocating backing_object
                   1291:                         *      will not remove it, since its reference
                   1292:                         *      count is at least 2.
                   1293:                         */
                   1294: 
                   1295:                        vm_object_reference(object->shadow = backing_object->shadow);
                   1296:                        object->shadow_offset += backing_object->shadow_offset;
                   1297: 
1.1.1.2 ! root     1298: #if 1
        !          1299:                        /* Mach 3.0 code */
        !          1300:                        /* [email protected], 12 Feb 1993 */
        !          1301: 
        !          1302:                        /*
        !          1303:                         *      Backing object might have had a copy pointer
        !          1304:                         *      to us.  If it did, clear it.
        !          1305:                         */
        !          1306:                         if (backing_object->copy == object)
        !          1307:                                backing_object->copy = NULL;
        !          1308: #endif
        !          1309: 
1.1       root     1310:                        /*      Drop the reference count on backing_object.
                   1311:                         *      Since its ref_count was at least 2, it
                   1312:                         *      will not vanish; so we don't need to call
                   1313:                         *      vm_object_deallocate.
                   1314:                         */
                   1315:                        backing_object->ref_count--;
                   1316:                        vm_object_unlock(backing_object);
                   1317: 
                   1318:                        object_bypasses ++;
                   1319: 
                   1320:                }
                   1321: 
                   1322:                /*
                   1323:                 *      Try again with this object's new backing object.
                   1324:                 */
                   1325:        }
                   1326: }
                   1327: 
                   1328: /*
                   1329:  *     vm_object_page_remove: [internal]
                   1330:  *
                   1331:  *     Removes all physical pages in the specified
                   1332:  *     object range from the object's list of pages.
                   1333:  *
                   1334:  *     The object must be locked.
                   1335:  */
                   1336: void vm_object_page_remove(object, start, end)
                   1337:        register vm_object_t    object;
                   1338:        register vm_offset_t    start;
                   1339:        register vm_offset_t    end;
                   1340: {
                   1341:        register vm_page_t      p, next;
                   1342: 
                   1343:        if (object == NULL)
                   1344:                return;
                   1345: 
                   1346:        p = (vm_page_t) queue_first(&object->memq);
                   1347:        while (!queue_end(&object->memq, (queue_entry_t) p)) {
                   1348:                next = (vm_page_t) queue_next(&p->listq);
                   1349:                if ((start <= p->offset) && (p->offset < end)) {
                   1350:                        pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
                   1351:                        vm_page_lock_queues();
                   1352:                        vm_page_free(p);
                   1353:                        vm_page_unlock_queues();
                   1354:                }
                   1355:                p = next;
                   1356:        }
                   1357: }
                   1358: 
                   1359: /*
                   1360:  *     Routine:        vm_object_coalesce
                   1361:  *     Function:       Coalesces two objects backing up adjoining
                   1362:  *                     regions of memory into a single object.
                   1363:  *
                   1364:  *     returns TRUE if objects were combined.
                   1365:  *
                   1366:  *     NOTE:   Only works at the moment if the second object is NULL -
                   1367:  *             if it's not, which object do we lock first?
                   1368:  *
                   1369:  *     Parameters:
                   1370:  *             prev_object     First object to coalesce
                   1371:  *             prev_offset     Offset into prev_object
                   1372:  *             next_object     Second object into coalesce
                   1373:  *             next_offset     Offset into next_object
                   1374:  *
                   1375:  *             prev_size       Size of reference to prev_object
                   1376:  *             next_size       Size of reference to next_object
                   1377:  *
                   1378:  *     Conditions:
                   1379:  *     The object must *not* be locked.
                   1380:  */
                   1381: boolean_t vm_object_coalesce(prev_object, next_object,
                   1382:                        prev_offset, next_offset,
                   1383:                        prev_size, next_size)
                   1384: 
                   1385:        register vm_object_t    prev_object;
                   1386:        vm_object_t     next_object;
                   1387:        vm_offset_t     prev_offset, next_offset;
                   1388:        vm_size_t       prev_size, next_size;
                   1389: {
                   1390:        vm_size_t       newsize;
                   1391: 
                   1392: #ifdef lint
                   1393:        next_offset++;
                   1394: #endif lint
                   1395: 
                   1396:        if (next_object != NULL) {
                   1397:                return(FALSE);
                   1398:        }
                   1399: 
                   1400:        if (prev_object == NULL) {
                   1401:                return(TRUE);
                   1402:        }
                   1403: 
                   1404:        vm_object_lock(prev_object);
                   1405: 
                   1406:        /*
                   1407:         *      Try to collapse the object first
                   1408:         */
                   1409:        vm_object_collapse(prev_object);
                   1410: 
                   1411:        /*
                   1412:         *      Can't coalesce if:
                   1413:         *      . more than one reference
                   1414:         *      . paged out
                   1415:         *      . shadows another object
                   1416:         *      . has a copy elsewhere
                   1417:         *      (any of which mean that the pages not mapped to
                   1418:         *      prev_entry may be in use anyway)
                   1419:         */
                   1420: 
                   1421:        if (prev_object->ref_count > 1 ||
                   1422:                prev_object->pager != NULL ||
                   1423:                prev_object->shadow != NULL ||
                   1424:                prev_object->copy != NULL) {
                   1425:                vm_object_unlock(prev_object);
                   1426:                return(FALSE);
                   1427:        }
                   1428: 
                   1429:        /*
                   1430:         *      Remove any pages that may still be in the object from
                   1431:         *      a previous deallocation.
                   1432:         */
                   1433: 
                   1434:        vm_object_page_remove(prev_object,
                   1435:                        prev_offset + prev_size,
                   1436:                        prev_offset + prev_size + next_size);
                   1437: 
                   1438:        /*
                   1439:         *      Extend the object if necessary.
                   1440:         */
                   1441:        newsize = prev_offset + prev_size + next_size;
                   1442:        if (newsize > prev_object->size)
                   1443:                prev_object->size = newsize;
                   1444: 
                   1445:        vm_object_unlock(prev_object);
                   1446:        return(TRUE);
                   1447: }
                   1448: 
                   1449: /*
                   1450:  *     vm_object_print:        [ debug ]
                   1451:  */
                   1452: void vm_object_print(object, full)
                   1453:        vm_object_t     object;
                   1454:        boolean_t       full;
                   1455: {
                   1456:        register vm_page_t      p;
                   1457:        extern indent;
                   1458: 
                   1459:        register int count;
                   1460: 
                   1461:        if (object == NULL)
                   1462:                return;
                   1463: 
                   1464:        iprintf("Object 0x%x: size=0x%x, res=%d, ref=%d, ",
                   1465:                (int) object, (int) object->size,
                   1466:                object->resident_page_count, object->ref_count);
                   1467:        printf("pager=0x%x+0x%x, shadow=(0x%x)+0x%x\n",
                   1468:               (int) object->pager, (int) object->paging_offset,
                   1469:               (int) object->shadow, (int) object->shadow_offset);
                   1470:        printf("cache: next=0x%x, prev=0x%x\n",
                   1471:               object->cached_list.next, object->cached_list.prev);
                   1472: 
                   1473:        if (!full)
                   1474:                return;
                   1475: 
                   1476:        indent += 2;
                   1477:        count = 0;
                   1478:        p = (vm_page_t) queue_first(&object->memq);
                   1479:        while (!queue_end(&object->memq, (queue_entry_t) p)) {
                   1480:                if (count == 0)
                   1481:                        iprintf("memory:=");
                   1482:                else if (count == 6) {
                   1483:                        printf("\n");
                   1484:                        iprintf(" ...");
                   1485:                        count = 0;
                   1486:                } else
                   1487:                        printf(",");
                   1488:                count++;
                   1489: 
                   1490:                printf("(off=0x%x,page=0x%x)", p->offset, VM_PAGE_TO_PHYS(p));
                   1491:                p = (vm_page_t) queue_next(&p->listq);
                   1492:        }
                   1493:        if (count != 0)
                   1494:                printf("\n");
                   1495:        indent -= 2;
                   1496: }

unix.superglobalmegacorp.com

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