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

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

unix.superglobalmegacorp.com

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