Annotation of kernel/vm/vm_object.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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