Annotation of XNU/osfmk/vm/vm_pageout.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988,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:  */
                     52: /*
                     53:  *     File:   vm/vm_pageout.c
                     54:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     55:  *     Date:   1985
                     56:  *
                     57:  *     The proverbial page-out daemon.
                     58:  */
                     59: #ifdef MACH_BSD
                     60: /* remove after component merge */
                     61: extern int     vnode_pager_workaround;
                     62: #endif
                     63: 
                     64: #include <mach_pagemap.h>
                     65: #include <mach_cluster_stats.h>
                     66: #include <mach_kdb.h>
                     67: #include <dipc.h>
                     68: #include <advisory_pageout.h>
                     69: 
                     70: #include <mach/mach_types.h>
                     71: #include <mach/memory_object.h>
                     72: #include <mach/memory_object_default.h>
                     73: #include <mach/mach_host_server.h>
                     74: #include <mach/vm_param.h>
                     75: #include <mach/vm_statistics.h>
                     76: #include <kern/host_statistics.h>
                     77: #include <kern/counters.h>
                     78: #include <kern/thread.h>
                     79: #include <kern/thread_swap.h>
                     80: #include <kern/xpr.h>
                     81: #include <vm/pmap.h>
                     82: #include <vm/vm_map.h>
                     83: #include <vm/vm_object.h>
                     84: #include <vm/vm_page.h>
                     85: #include <vm/vm_pageout.h>
                     86: #include <machine/vm_tuning.h>
                     87: #include <kern/misc_protos.h>
                     88: 
                     89: extern ipc_port_t      memory_manager_default;
                     90: 
                     91: #ifndef        VM_PAGE_LAUNDRY_MAX
                     92: #define        VM_PAGE_LAUNDRY_MAX     10      /* outstanding DMM page cleans */
                     93: #endif /* VM_PAGEOUT_LAUNDRY_MAX */
                     94: 
                     95: #ifndef        VM_PAGEOUT_BURST_MAX
                     96: #define        VM_PAGEOUT_BURST_MAX    10      /* simultaneous EMM page cleans */
                     97: #endif /* VM_PAGEOUT_BURST_MAX */
                     98: 
                     99: #ifndef        VM_PAGEOUT_DISCARD_MAX
                    100: #define        VM_PAGEOUT_DISCARD_MAX  68      /* simultaneous EMM page cleans */
                    101: #endif /* VM_PAGEOUT_DISCARD_MAX */
                    102: 
                    103: #ifndef        VM_PAGEOUT_BURST_WAIT
                    104: #define        VM_PAGEOUT_BURST_WAIT   30      /* milliseconds per page */
                    105: #endif /* VM_PAGEOUT_BURST_WAIT */
                    106: 
                    107: #ifndef        VM_PAGEOUT_EMPTY_WAIT
                    108: #define VM_PAGEOUT_EMPTY_WAIT  200     /* milliseconds */
                    109: #endif /* VM_PAGEOUT_EMPTY_WAIT */
                    110: 
                    111: /*
                    112:  *     To obtain a reasonable LRU approximation, the inactive queue
                    113:  *     needs to be large enough to give pages on it a chance to be
                    114:  *     referenced a second time.  This macro defines the fraction
                    115:  *     of active+inactive pages that should be inactive.
                    116:  *     The pageout daemon uses it to update vm_page_inactive_target.
                    117:  *
                    118:  *     If vm_page_free_count falls below vm_page_free_target and
                    119:  *     vm_page_inactive_count is below vm_page_inactive_target,
                    120:  *     then the pageout daemon starts running.
                    121:  */
                    122: 
                    123: #ifndef        VM_PAGE_INACTIVE_TARGET
                    124: #define        VM_PAGE_INACTIVE_TARGET(avail)  ((avail) * 2 / 3)
                    125: #endif /* VM_PAGE_INACTIVE_TARGET */
                    126: 
                    127: /*
                    128:  *     Once the pageout daemon starts running, it keeps going
                    129:  *     until vm_page_free_count meets or exceeds vm_page_free_target.
                    130:  */
                    131: 
                    132: #ifndef        VM_PAGE_FREE_TARGET
                    133: #define        VM_PAGE_FREE_TARGET(free)       (15 + (free) / 80)
                    134: #endif /* VM_PAGE_FREE_TARGET */
                    135: 
                    136: /*
                    137:  *     The pageout daemon always starts running once vm_page_free_count
                    138:  *     falls below vm_page_free_min.
                    139:  */
                    140: 
                    141: #ifndef        VM_PAGE_FREE_MIN
                    142: #define        VM_PAGE_FREE_MIN(free)  (10 + (free) / 100)
                    143: #endif /* VM_PAGE_FREE_MIN */
                    144: 
                    145: /*
                    146:  *     When vm_page_free_count falls below vm_page_free_reserved,
                    147:  *     only vm-privileged threads can allocate pages.  vm-privilege
                    148:  *     allows the pageout daemon and default pager (and any other
                    149:  *     associated threads needed for default pageout) to continue
                    150:  *     operation by dipping into the reserved pool of pages.
                    151:  */
                    152: 
                    153: #ifndef        VM_PAGE_FREE_RESERVED
                    154: #define        VM_PAGE_FREE_RESERVED   \
                    155:        ((8 * VM_PAGE_LAUNDRY_MAX) + NCPUS)
                    156: #endif /* VM_PAGE_FREE_RESERVED */
                    157: 
                    158: 
                    159: /*
                    160:  * Forward declarations for internal routines.
                    161:  */
                    162: extern void vm_pageout_continue(void);
                    163: extern void vm_pageout_scan(void);
                    164: extern void vm_pageout_throttle(vm_page_t m);
                    165: extern vm_page_t vm_pageout_cluster_page(
                    166:                        vm_object_t     object,
                    167:                        vm_offset_t     offset,
                    168:                        boolean_t       precious_clean);
                    169: 
                    170: unsigned int vm_pageout_reserved_internal = 0;
                    171: unsigned int vm_pageout_reserved_really = 0;
                    172: 
                    173: unsigned int vm_page_laundry_max = 0;          /* # of clusters outstanding */
                    174: unsigned int vm_page_laundry_min = 0;
                    175: unsigned int vm_pageout_burst_max = 0;
                    176: unsigned int vm_pageout_burst_wait = 0;                /* milliseconds per page */
                    177: unsigned int vm_pageout_empty_wait = 0;                /* milliseconds */
                    178: unsigned int vm_pageout_burst_min = 0;
                    179: unsigned int vm_pageout_pause_count = 0;
                    180: unsigned int vm_pageout_pause_max = 0;
                    181: unsigned int vm_free_page_pause = 100;                 /* milliseconds */
                    182: 
                    183: /*
                    184:  *     These variables record the pageout daemon's actions:
                    185:  *     how many pages it looks at and what happens to those pages.
                    186:  *     No locking needed because only one thread modifies the variables.
                    187:  */
                    188: 
                    189: unsigned int vm_pageout_active = 0;            /* debugging */
                    190: unsigned int vm_pageout_inactive = 0;          /* debugging */
                    191: unsigned int vm_pageout_inactive_throttled = 0;        /* debugging */
                    192: unsigned int vm_pageout_inactive_forced = 0;   /* debugging */
                    193: unsigned int vm_pageout_inactive_nolock = 0;   /* debugging */
                    194: unsigned int vm_pageout_inactive_avoid = 0;    /* debugging */
                    195: unsigned int vm_pageout_inactive_busy = 0;     /* debugging */
                    196: unsigned int vm_pageout_inactive_absent = 0;   /* debugging */
                    197: unsigned int vm_pageout_inactive_used = 0;     /* debugging */
                    198: unsigned int vm_pageout_inactive_clean = 0;    /* debugging */
                    199: unsigned int vm_pageout_inactive_dirty = 0;    /* debugging */
                    200: unsigned int vm_pageout_dirty_no_pager = 0;    /* debugging */
                    201: unsigned int vm_pageout_inactive_pinned = 0;   /* debugging */
                    202: unsigned int vm_pageout_inactive_limbo = 0;    /* debugging */
                    203: unsigned int vm_pageout_setup_limbo = 0;       /* debugging */
                    204: unsigned int vm_pageout_setup_unprepped = 0;   /* debugging */
                    205: unsigned int vm_stat_discard = 0;              /* debugging */
                    206: unsigned int vm_stat_discard_sent = 0;         /* debugging */
                    207: unsigned int vm_stat_discard_failure = 0;      /* debugging */
                    208: unsigned int vm_stat_discard_throttle = 0;     /* debugging */
                    209: unsigned int vm_pageout_scan_active_emm_throttle = 0;          /* debugging */
                    210: unsigned int vm_pageout_scan_active_emm_throttle_success = 0;  /* debugging */
                    211: unsigned int vm_pageout_scan_active_emm_throttle_failure = 0;  /* debugging */
                    212: unsigned int vm_pageout_scan_inactive_emm_throttle = 0;                /* debugging */
                    213: unsigned int vm_pageout_scan_inactive_emm_throttle_success = 0;        /* debugging */
                    214: unsigned int vm_pageout_scan_inactive_emm_throttle_failure = 0;        /* debugging */
                    215: 
                    216: 
                    217: unsigned int vm_pageout_out_of_line  = 0;
                    218: unsigned int vm_pageout_in_place  = 0;
                    219: /*
                    220:  *     Routine:        vm_pageout_object_allocate
                    221:  *     Purpose:
                    222:  *             Allocate an object for use as out-of-line memory in a
                    223:  *             data_return/data_initialize message.
                    224:  *             The page must be in an unlocked object.
                    225:  *
                    226:  *             If the page belongs to a trusted pager, cleaning in place
                    227:  *             will be used, which utilizes a special "pageout object"
                    228:  *             containing private alias pages for the real page frames.
                    229:  *             Untrusted pagers use normal out-of-line memory.
                    230:  */
                    231: vm_object_t
                    232: vm_pageout_object_allocate(
                    233:        vm_page_t       m,
                    234:        vm_size_t       size,
                    235:        vm_offset_t     offset)
                    236: {
                    237:        vm_object_t     object = m->object;
                    238:        vm_object_t     new_object;
                    239: 
                    240:        assert(object->pager_ready);
                    241: 
                    242:        if (object->pager_trusted || object->internal)
                    243:                vm_pageout_throttle(m);
                    244: 
                    245:        new_object = vm_object_allocate(size);
                    246: 
                    247:        if (object->pager_trusted) {
                    248:                assert (offset < object->size);
                    249: 
                    250:                vm_object_lock(new_object);
                    251:                new_object->pageout = TRUE;
                    252:                new_object->shadow = object;
                    253:                new_object->can_persist = FALSE;
                    254:                new_object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
                    255:                new_object->shadow_offset = offset;
                    256:                vm_object_unlock(new_object);
                    257: 
                    258:                /*
                    259:                 * Take a paging reference on the object. This will be dropped
                    260:                 * in vm_pageout_object_terminate()
                    261:                 */
                    262:                vm_object_lock(object);
                    263:                vm_object_paging_begin(object);
                    264:                vm_object_unlock(object);
                    265: 
                    266:                vm_pageout_in_place++;
                    267:        } else
                    268:                vm_pageout_out_of_line++;
                    269:        return(new_object);
                    270: }
                    271: 
                    272: #if MACH_CLUSTER_STATS
                    273: unsigned long vm_pageout_cluster_dirtied = 0;
                    274: unsigned long vm_pageout_cluster_cleaned = 0;
                    275: unsigned long vm_pageout_cluster_collisions = 0;
                    276: unsigned long vm_pageout_cluster_clusters = 0;
                    277: unsigned long vm_pageout_cluster_conversions = 0;
                    278: unsigned long vm_pageout_target_collisions = 0;
                    279: unsigned long vm_pageout_target_page_dirtied = 0;
                    280: unsigned long vm_pageout_target_page_freed = 0;
                    281: unsigned long vm_pageout_target_page_pinned = 0;
                    282: unsigned long vm_pageout_target_page_limbo = 0;
                    283: #define CLUSTER_STAT(clause)   clause
                    284: #else  /* MACH_CLUSTER_STATS */
                    285: #define CLUSTER_STAT(clause)
                    286: #endif /* MACH_CLUSTER_STATS */
                    287: 
                    288: /* 
                    289:  *     Routine:        vm_pageout_object_terminate
                    290:  *     Purpose:
                    291:  *             Destroy the pageout_object allocated by
                    292:  *             vm_pageout_object_allocate(), and perform all of the
                    293:  *             required cleanup actions.
                    294:  * 
                    295:  *     In/Out conditions:
                    296:  *             The object must be locked, and will be returned locked.
                    297:  */
                    298: void
                    299: vm_pageout_object_terminate(
                    300:        vm_object_t     object)
                    301: {
                    302:        vm_object_t     shadow_object;
                    303: 
                    304:        /*
                    305:         * Deal with the deallocation (last reference) of a pageout object
                    306:         * (used for cleaning-in-place) by dropping the paging references/
                    307:         * freeing pages in the original object.
                    308:         */
                    309: 
                    310:        assert(object->pageout);
                    311:        shadow_object = object->shadow;
                    312:        vm_object_lock(shadow_object);
                    313: 
                    314:        while (!queue_empty(&object->memq)) {
                    315:                vm_page_t p, m;
                    316:                vm_offset_t offset;
                    317: 
                    318:                p = (vm_page_t) queue_first(&object->memq);
                    319: 
                    320:                assert(p->private);
                    321:                assert(p->pageout);
                    322:                p->pageout = FALSE;
                    323:                assert(!p->cleaning);
                    324: 
                    325:                offset = p->offset;
                    326:                VM_PAGE_FREE(p);
                    327:                p = VM_PAGE_NULL;
                    328: 
                    329:                m = vm_page_lookup(shadow_object,
                    330:                        offset + object->shadow_offset);
                    331: 
                    332:                if(m == VM_PAGE_NULL)
                    333:                        continue;
                    334:                assert(m->cleaning);
                    335: 
                    336:                /*
                    337:                 * Account for the paging reference taken when
                    338:                 * m->cleaning was set on this page.
                    339:                 */
                    340:                vm_object_paging_end(shadow_object);
                    341:                assert((m->dirty) || (m->precious) ||
                    342:                                (m->busy && m->cleaning));
                    343: 
                    344:                /*
                    345:                 * Handle the trusted pager throttle.
                    346:                 */
                    347:                vm_page_lock_queues();
                    348:                if (m->laundry) {
                    349:                    vm_page_laundry_count--;
                    350:                    m->laundry = FALSE;
                    351:                    if (vm_page_laundry_count < vm_page_laundry_min) {
                    352:                        vm_page_laundry_min = 0;
                    353:                        thread_wakeup((event_t) &vm_page_laundry_count);
                    354:                    }
                    355:                }
                    356: 
                    357:                /*
                    358:                 * Handle the "target" page(s). These pages are to be freed if
                    359:                 * successfully cleaned. Target pages are always busy, and are
                    360:                 * wired exactly once. The initial target pages are not mapped,
                    361:                 * (so cannot be referenced or modified) but converted target
                    362:                 * pages may have been modified between the selection as an
                    363:                 * adjacent page and conversion to a target.
                    364:                 */
                    365:                if (m->pageout) {
                    366:                        assert(m->busy);
                    367:                        assert(m->wire_count == 1);
                    368:                        m->cleaning = FALSE;
                    369:                        m->pageout = FALSE;
                    370: #if MACH_CLUSTER_STATS
                    371:                        if (m->wanted) vm_pageout_target_collisions++;
                    372: #endif
                    373:                        /*
                    374:                         * Revoke all access to the page. Since the object is
                    375:                         * locked, and the page is busy, this prevents the page
                    376:                         * from being dirtied after the pmap_is_modified() call
                    377:                         * returns.
                    378:                         */
                    379:                        pmap_page_protect(m->phys_addr, VM_PROT_NONE);
                    380: 
                    381:                        /*
                    382:                         * Since the page is left "dirty" but "not modifed", we
                    383:                         * can detect whether the page was redirtied during
                    384:                         * pageout by checking the modify state.
                    385:                         */
                    386:                        m->dirty = pmap_is_modified(m->phys_addr);
                    387: 
                    388:                        if (m->dirty) {
                    389:                                CLUSTER_STAT(vm_pageout_target_page_dirtied++;)
                    390:                                vm_page_unwire(m);/* reactivates */
                    391:                                VM_STAT(reactivations++);
                    392:                                PAGE_WAKEUP_DONE(m);
                    393:                        } else if (m->prep_pin_count != 0) {
                    394:                                vm_page_pin_lock();
                    395:                                if (m->pin_count != 0) {
                    396:                                        /* page is pinned; reactivate */
                    397:                                        CLUSTER_STAT(
                    398:                                            vm_pageout_target_page_pinned++;)
                    399:                                        vm_page_unwire(m);/* reactivates */
                    400:                                        VM_STAT(reactivations++);
                    401:                                        PAGE_WAKEUP_DONE(m);
                    402:                                } else {
                    403:                                        /*
                    404:                                         * page is prepped but not pinned; send
                    405:                                         * it into limbo.  Note that
                    406:                                         * vm_page_free (which will be called
                    407:                                         * after releasing the pin lock) knows
                    408:                                         * how to handle a page with limbo set.
                    409:                                         */
                    410:                                        m->limbo = TRUE;
                    411:                                        CLUSTER_STAT(
                    412:                                            vm_pageout_target_page_limbo++;)
                    413:                                }
                    414:                                vm_page_pin_unlock();
                    415:                                if (m->limbo)
                    416:                                        vm_page_free(m);
                    417:                        } else {
                    418:                                CLUSTER_STAT(vm_pageout_target_page_freed++;)
                    419:                                vm_page_free(m);/* clears busy, etc. */
                    420:                        }
                    421:                        vm_page_unlock_queues();
                    422:                        continue;
                    423:                }
                    424:                /*
                    425:                 * Handle the "adjacent" pages. These pages were cleaned in
                    426:                 * place, and should be left alone.
                    427:                 * If prep_pin_count is nonzero, then someone is using the
                    428:                 * page, so make it active.
                    429:                 */
                    430:                if (!m->active && !m->inactive) {
                    431:                        if (m->reference || m->prep_pin_count != 0)
                    432:                                vm_page_activate(m);
                    433:                        else
                    434:                                vm_page_deactivate(m);
                    435:                }
                    436:                if((m->busy) && (m->cleaning)) {
                    437: 
                    438:                        /* the request_page_list case, (COPY_OUT_FROM FALSE) */
                    439:                        m->busy = FALSE;
                    440: 
                    441:                        /* We do not re-set m->dirty ! */
                    442:                        /* The page was busy so no extraneous activity     */
                    443:                        /* could have occured. COPY_INTO is a read into the */
                    444:                        /* new pages. CLEAN_IN_PLACE does actually write   */
                    445:                        /* out the pages but handling outside of this code */
                    446:                        /* will take care of resetting dirty. We clear the */
                    447:                        /* modify however for the Programmed I/O case.     */ 
                    448:                        pmap_clear_modify(m->phys_addr);
                    449:                        if(m->absent) {
                    450:                                m->absent = FALSE;
                    451:                                if(shadow_object->absent_count == 1)
                    452:                                        vm_object_absent_release(shadow_object);
                    453:                                else
                    454:                                        shadow_object->absent_count--;
                    455:                        }
                    456:                        m->overwriting = FALSE;
                    457:                } else if (m->overwriting) {
                    458:                        /* alternate request page list, write to page_list */
                    459:                        /* case.  Occurs when the original page was wired  */
                    460:                        /* at the time of the list request */
                    461:                        assert(m->wire_count != 0);
                    462:                        vm_page_unwire(m);/* reactivates */
                    463:                        m->overwriting = FALSE;
                    464:                } else {
                    465:                /*
                    466:                 * Set the dirty state according to whether or not the page was
                    467:                 * modified during the pageout. Note that we purposefully do
                    468:                 * NOT call pmap_clear_modify since the page is still mapped.
                    469:                 * If the page were to be dirtied between the 2 calls, this
                    470:                 * this fact would be lost. This code is only necessary to
                    471:                 * maintain statistics, since the pmap module is always
                    472:                 * consulted if m->dirty is false.
                    473:                 */
                    474: #if MACH_CLUSTER_STATS
                    475:                        m->dirty = pmap_is_modified(m->phys_addr);
                    476: 
                    477:                        if (m->dirty)   vm_pageout_cluster_dirtied++;
                    478:                        else            vm_pageout_cluster_cleaned++;
                    479:                        if (m->wanted)  vm_pageout_cluster_collisions++;
                    480: #else
                    481:                        m->dirty = 0;
                    482: #endif
                    483:                }
                    484:                m->cleaning = FALSE;
                    485: 
                    486: 
                    487:                /*
                    488:                 * Wakeup any thread waiting for the page to be un-cleaning.
                    489:                 */
                    490:                PAGE_WAKEUP(m);
                    491:                vm_page_unlock_queues();
                    492:        }
                    493:        /*
                    494:         * Account for the paging reference taken in vm_paging_object_allocate.
                    495:         */
                    496:        vm_object_paging_end(shadow_object);
                    497:        vm_object_unlock(shadow_object);
                    498: 
                    499:        assert(object->ref_count == 0);
                    500:        assert(object->paging_in_progress == 0);
                    501:        assert(object->resident_page_count == 0);
                    502:        return;
                    503: }
                    504: 
                    505: /*
                    506:  *     Routine:        vm_pageout_setup
                    507:  *     Purpose:
                    508:  *             Set up a page for pageout (clean & flush).
                    509:  *
                    510:  *             Move the page to a new object, as part of which it will be
                    511:  *             sent to its memory manager in a memory_object_data_write or
                    512:  *             memory_object_initialize message.
                    513:  *
                    514:  *             The "new_object" and "new_offset" arguments
                    515:  *             indicate where the page should be moved.
                    516:  *
                    517:  *     In/Out conditions:
                    518:  *             The page in question must not be on any pageout queues,
                    519:  *             and must be busy.  The object to which it belongs
                    520:  *             must be unlocked, and the caller must hold a paging
                    521:  *             reference to it.  The new_object must not be locked.
                    522:  *
                    523:  *             This routine returns a pointer to a place-holder page,
                    524:  *             inserted at the same offset, to block out-of-order
                    525:  *             requests for the page.  The place-holder page must
                    526:  *             be freed after the data_write or initialize message
                    527:  *             has been sent.
                    528:  *
                    529:  *             The original page is put on a paging queue and marked
                    530:  *             not busy on exit.
                    531:  */
                    532: vm_page_t
                    533: vm_pageout_setup(
                    534:        register vm_page_t      m,
                    535:        register vm_object_t    new_object,
                    536:        vm_offset_t             new_offset)
                    537: {
                    538:        register vm_object_t    old_object = m->object;
                    539:        vm_offset_t             paging_offset;
                    540:        vm_offset_t             offset;
                    541:        register vm_page_t      holding_page;
                    542:        register vm_page_t      new_m;
                    543:        register vm_page_t      new_page;
                    544:        boolean_t               need_to_wire = FALSE;
                    545: 
                    546: 
                    547:         XPR(XPR_VM_PAGEOUT,
                    548:      "vm_pageout_setup, obj 0x%X off 0x%X page 0x%X new obj 0x%X offset 0x%X\n",
                    549:                 (integer_t)m->object, (integer_t)m->offset, 
                    550:                (integer_t)m, (integer_t)new_object, 
                    551:                (integer_t)new_offset);
                    552:        assert(m && m->busy && !m->absent && !m->fictitious && !m->error &&
                    553:                !m->restart);
                    554: 
                    555:        assert(m->dirty || m->precious);
                    556: 
                    557:        /*
                    558:         *      Create a place-holder page where the old one was, to prevent
                    559:         *      attempted pageins of this page while we're unlocked.
                    560:         *      If the pageout daemon put this page in limbo and we're not
                    561:         *      going to clean in place, get another fictitious page to
                    562:         *      exchange for it now.
                    563:         */
                    564:        VM_PAGE_GRAB_FICTITIOUS(holding_page);
                    565: 
                    566:        if (m->limbo)
                    567:                VM_PAGE_GRAB_FICTITIOUS(new_page);
                    568: 
                    569:        vm_object_lock(old_object);
                    570: 
                    571:        offset = m->offset;
                    572:        paging_offset = offset + old_object->paging_offset;
                    573: 
                    574:        if (old_object->pager_trusted) {
                    575:                /*
                    576:                 * This pager is trusted, so we can clean this page
                    577:                 * in place. Leave it in the old object, and mark it
                    578:                 * cleaning & pageout.
                    579:                 */
                    580:                new_m = holding_page;
                    581:                holding_page = VM_PAGE_NULL;
                    582: 
                    583:                /*
                    584:                 * If the pageout daemon put this page in limbo, exchange the
                    585:                 * identities of the limbo page and the new fictitious page,
                    586:                 * and continue with the new page, unless the prep count has
                    587:                 * gone to zero in the meantime (which means no one is
                    588:                 * interested in the page any more).  In that case, just clear
                    589:                 * the limbo bit and free the extra fictitious page.
                    590:                 */
                    591:                if (m->limbo) {
                    592:                        if (m->prep_pin_count == 0) {
                    593:                                /* page doesn't have to be in limbo any more */
                    594:                                m->limbo = FALSE;
                    595:                                vm_page_free(new_page);
                    596:                                vm_pageout_setup_unprepped++;
                    597:                        } else {
                    598:                                vm_page_lock_queues();
                    599:                                VM_PAGE_QUEUES_REMOVE(m);
                    600:                                vm_page_remove(m);
                    601:                                vm_page_limbo_exchange(m, new_page);
                    602:                                vm_pageout_setup_limbo++;
                    603:                                vm_page_release_limbo(m);
                    604:                                m = new_page;
                    605:                                vm_page_insert(m, old_object, offset);
                    606:                                vm_page_unlock_queues();
                    607:                        }
                    608:                }
                    609: 
                    610:                /*
                    611:                 * Set up new page to be private shadow of real page.
                    612:                 */
                    613:                new_m->phys_addr = m->phys_addr;
                    614:                new_m->fictitious = FALSE;
                    615:                new_m->private = TRUE;
                    616:                new_m->pageout = TRUE;
                    617: 
                    618:                /*
                    619:                 * Mark real page as cleaning (indicating that we hold a
                    620:                 * paging reference to be released via m_o_d_r_c) and
                    621:                 * pageout (indicating that the page should be freed
                    622:                 * when the pageout completes).
                    623:                 */
                    624:                pmap_clear_modify(m->phys_addr);
                    625:                vm_page_lock_queues();
                    626:                vm_page_wire(new_m);
                    627:                m->cleaning = TRUE;
                    628:                m->pageout = TRUE;
                    629: 
                    630:                vm_page_wire(m);
                    631:                assert(m->wire_count == 1);
                    632:                vm_page_unlock_queues();
                    633: 
                    634:                m->dirty = TRUE;
                    635:                m->precious = FALSE;
                    636:                m->page_lock = VM_PROT_NONE;
                    637:                m->unusual = FALSE;
                    638:                m->unlock_request = VM_PROT_NONE;
                    639:        } else {
                    640:                /*
                    641:                 * Cannot clean in place, so rip the old page out of the
                    642:                 * object, and stick the holding page in. Set new_m to the
                    643:                 * page in the new object.
                    644:                 */
                    645:                vm_page_lock_queues();
                    646:                VM_PAGE_QUEUES_REMOVE(m);
                    647:                vm_page_remove(m);
                    648: 
                    649:                /*
                    650:                 * If the pageout daemon put this page in limbo, exchange the
                    651:                 * identities of the limbo page and the new fictitious page,
                    652:                 * and continue with the new page, unless the prep count has
                    653:                 * gone to zero in the meantime (which means no one is
                    654:                 * interested in the page any more).  In that case, just clear
                    655:                 * the limbo bit and free the extra fictitious page.
                    656:                 */
                    657:                if (m->limbo) {
                    658:                        if (m->prep_pin_count == 0) {
                    659:                                /* page doesn't have to be in limbo any more */
                    660:                                m->limbo = FALSE;
                    661:                                vm_page_free(new_page);
                    662:                                vm_pageout_setup_unprepped++;
                    663:                        } else {
                    664:                                vm_page_limbo_exchange(m, new_page);
                    665:                                vm_pageout_setup_limbo++;
                    666:                                vm_page_release_limbo(m);
                    667:                                m = new_page;
                    668:                        }
                    669:                }
                    670:                
                    671:                vm_page_insert(holding_page, old_object, offset);
                    672:                vm_page_unlock_queues();
                    673: 
                    674:                m->dirty = TRUE;
                    675:                m->precious = FALSE;
                    676:                new_m = m;
                    677:                new_m->page_lock = VM_PROT_NONE;
                    678:                new_m->unlock_request = VM_PROT_NONE;
                    679: 
                    680:                if (old_object->internal)
                    681:                        need_to_wire = TRUE;
                    682:        }
                    683:        /*
                    684:         *      Record that this page has been written out
                    685:         */
                    686: #if    MACH_PAGEMAP
                    687:        vm_external_state_set(old_object->existence_map, offset);
                    688: #endif /* MACH_PAGEMAP */
                    689: 
                    690:        vm_object_unlock(old_object);
                    691: 
                    692:        vm_object_lock(new_object);
                    693: 
                    694:        /*
                    695:         *      Put the page into the new object. If it is a not wired
                    696:         *      (if it's the real page) it will be activated.
                    697:         */
                    698: 
                    699:        vm_page_lock_queues();
                    700:        vm_page_insert(new_m, new_object, new_offset);
                    701:        if (need_to_wire)
                    702:                vm_page_wire(new_m);
                    703:        else
                    704:                vm_page_activate(new_m);
                    705:        PAGE_WAKEUP_DONE(new_m);
                    706:        vm_page_unlock_queues();
                    707: 
                    708:        vm_object_unlock(new_object);
                    709: 
                    710:        /*
                    711:         *      Return the placeholder page to simplify cleanup.
                    712:         */
                    713:        return (holding_page);
                    714: }
                    715: 
                    716: /*
                    717:  * Routine:    vm_pageclean_setup
                    718:  *
                    719:  * Purpose:    setup a page to be cleaned (made non-dirty), but not
                    720:  *             necessarily flushed from the VM page cache.
                    721:  *             This is accomplished by cleaning in place.
                    722:  *
                    723:  *             The page must not be busy, and the object and page
                    724:  *             queues must be locked.
                    725:  *             
                    726:  */
                    727: void
                    728: vm_pageclean_setup(
                    729:        vm_page_t       m,
                    730:        vm_page_t       new_m,
                    731:        vm_object_t     new_object,
                    732:        vm_offset_t     new_offset)
                    733: {
                    734:        vm_object_t old_object = m->object;
                    735:        assert(!m->busy);
                    736:        assert(!m->cleaning);
                    737: 
                    738:        XPR(XPR_VM_PAGEOUT,
                    739:     "vm_pageclean_setup, obj 0x%X off 0x%X page 0x%X new 0x%X new_off 0x%X\n",
                    740:                (integer_t)old_object, m->offset, (integer_t)m, 
                    741:                (integer_t)new_m, new_offset);
                    742: 
                    743:        pmap_clear_modify(m->phys_addr);
                    744:        vm_object_paging_begin(old_object);
                    745: 
                    746:        /*
                    747:         *      Record that this page has been written out
                    748:         */
                    749: #if    MACH_PAGEMAP
                    750:        vm_external_state_set(old_object->existence_map, m->offset);
                    751: #endif /*MACH_PAGEMAP*/
                    752: 
                    753:        /*
                    754:         * Mark original page as cleaning in place.
                    755:         */
                    756:        m->cleaning = TRUE;
                    757:        m->dirty = TRUE;
                    758:        m->precious = FALSE;
                    759: 
                    760:        /*
                    761:         * Convert the fictitious page to a private shadow of
                    762:         * the real page.
                    763:         */
                    764:        assert(new_m->fictitious);
                    765:        new_m->fictitious = FALSE;
                    766:        new_m->private = TRUE;
                    767:        new_m->pageout = TRUE;
                    768:        new_m->phys_addr = m->phys_addr;
                    769:        vm_page_wire(new_m);
                    770: 
                    771:        vm_page_insert(new_m, new_object, new_offset);
                    772:        assert(!new_m->wanted);
                    773:        new_m->busy = FALSE;
                    774: }
                    775: 
                    776: void
                    777: vm_pageclean_copy(
                    778:        vm_page_t       m,
                    779:        vm_page_t       new_m,
                    780:        vm_object_t     new_object,
                    781:        vm_offset_t     new_offset)
                    782: {
                    783:        XPR(XPR_VM_PAGEOUT,
                    784:        "vm_pageclean_copy, page 0x%X new_m 0x%X new_obj 0x%X offset 0x%X\n",
                    785:                m, new_m, new_object, new_offset, 0);
                    786: 
                    787:        assert((!m->busy) && (!m->cleaning));
                    788: 
                    789:        assert(!new_m->private && !new_m->fictitious);
                    790: 
                    791:        pmap_clear_modify(m->phys_addr);
                    792: 
                    793:        m->busy = TRUE;
                    794:        vm_object_paging_begin(m->object);
                    795:        vm_page_unlock_queues();
                    796:        vm_object_unlock(m->object);
                    797: 
                    798:        /*
                    799:         * Copy the original page to the new page.
                    800:         */
                    801:        vm_page_copy(m, new_m);
                    802: 
                    803:        /*
                    804:         * Mark the old page as clean. A request to pmap_is_modified
                    805:         * will get the right answer.
                    806:         */
                    807:        vm_object_lock(m->object);
                    808:        m->dirty = FALSE;
                    809: 
                    810:        vm_object_paging_end(m->object);
                    811: 
                    812:        vm_page_lock_queues();
                    813:        if (!m->active && !m->inactive)
                    814:                vm_page_activate(m);
                    815:        PAGE_WAKEUP_DONE(m);
                    816: 
                    817:        vm_page_insert(new_m, new_object, new_offset);
                    818:        vm_page_activate(new_m);
                    819:        new_m->busy = FALSE;    /* No other thread can be waiting */
                    820: }
                    821: 
                    822: 
                    823: /*
                    824:  *     Routine:        vm_pageout_initialize_page
                    825:  *     Purpose:
                    826:  *             Causes the specified page to be initialized in
                    827:  *             the appropriate memory object. This routine is used to push
                    828:  *             pages into a copy-object when they are modified in the
                    829:  *             permanent object.
                    830:  *
                    831:  *             The page is moved to a temporary object and paged out.
                    832:  *
                    833:  *     In/out conditions:
                    834:  *             The page in question must not be on any pageout queues.
                    835:  *             The object to which it belongs must be locked.
                    836:  *             The page must be busy, but not hold a paging reference.
                    837:  *
                    838:  *     Implementation:
                    839:  *             Move this page to a completely new object.
                    840:  */
                    841: void   
                    842: vm_pageout_initialize_page(
                    843:        vm_page_t       m)
                    844: {
                    845:        vm_map_copy_t   copy;
                    846:        vm_object_t     new_object;
                    847:        vm_object_t     object;
                    848:        vm_offset_t     paging_offset;
                    849:        vm_page_t       holding_page;
                    850: 
                    851: 
                    852:        XPR(XPR_VM_PAGEOUT,
                    853:                "vm_pageout_initialize_page, page 0x%X\n",
                    854:                (integer_t)m, 0, 0, 0, 0);
                    855:        assert(m->busy);
                    856: 
                    857:        /*
                    858:         *      Verify that we really want to clean this page
                    859:         */
                    860:        assert(!m->absent);
                    861:        assert(!m->error);
                    862:        assert(m->dirty);
                    863: 
                    864:        /*
                    865:         *      Create a paging reference to let us play with the object.
                    866:         */
                    867:        object = m->object;
                    868:        paging_offset = m->offset + object->paging_offset;
                    869:        vm_object_paging_begin(object);
                    870:        vm_object_unlock(object);
                    871:        if (m->absent || m->error || m->restart ||
                    872:            (!m->dirty && !m->precious)) {
                    873:                VM_PAGE_FREE(m);
                    874:                panic("reservation without pageout?"); /* alan */
                    875:                return;
                    876:        }
                    877: 
                    878:        /* set the page for future call to vm_fault_list_request */
                    879:        holding_page = NULL;
                    880:        vm_object_lock(m->object);
                    881:        vm_page_lock_queues();
                    882:        pmap_clear_modify(m->phys_addr);
                    883:        m->dirty = TRUE;
                    884:                m->busy = TRUE;
                    885:                m->list_req_pending = TRUE;
                    886:                m->cleaning = TRUE;
                    887:        m->pageout = TRUE;
                    888:        vm_page_wire(m);
                    889:        vm_page_unlock_queues();
                    890:        vm_object_unlock(m->object);
                    891:        vm_pageout_throttle(m);
                    892:        copy = NULL;
                    893: 
                    894:        VM_STAT(pageouts++);
                    895:        /* VM_STAT(pages_pagedout++); */
                    896: 
                    897:        /*
                    898:         *      Write the data to its pager.
                    899:         *      Note that the data is passed by naming the new object,
                    900:         *      not a virtual address; the pager interface has been
                    901:         *      manipulated to use the "internal memory" data type.
                    902:         *      [The object reference from its allocation is donated
                    903:         *      to the eventual recipient.]
                    904:         */
                    905:        memory_object_data_initialize(object->pager,
                    906:                                        object->pager_request,
                    907:                                        paging_offset,
                    908:                                        POINTER_T(copy),
                    909:                                        PAGE_SIZE);
                    910: 
                    911:        vm_object_lock(object);
                    912: }
                    913: 
                    914: #if    MACH_CLUSTER_STATS
                    915: #define MAXCLUSTERPAGES        16
                    916: struct {
                    917:        unsigned long pages_in_cluster;
                    918:        unsigned long pages_at_higher_offsets;
                    919:        unsigned long pages_at_lower_offsets;
                    920: } cluster_stats[MAXCLUSTERPAGES];
                    921: #endif /* MACH_CLUSTER_STATS */
                    922: 
                    923: boolean_t allow_clustered_pageouts = TRUE;
                    924: 
                    925: /*
                    926:  * vm_pageout_cluster:
                    927:  *
                    928:  * Given a page, page it out, and attempt to clean adjacent pages
                    929:  * in the same operation.
                    930:  *
                    931:  * The page must be busy, and the object unlocked w/ paging reference
                    932:  * to prevent deallocation or collapse. The page must not be on any
                    933:  * pageout queue.
                    934:  */
                    935: void
                    936: vm_pageout_cluster(
                    937:        vm_page_t m)
                    938: {
                    939:        vm_object_t     object = m->object;
                    940:        vm_offset_t     offset = m->offset;     /* from vm_object start */
                    941:        vm_offset_t     paging_offset = m->offset + object->paging_offset;
                    942:        vm_object_t     new_object;
                    943:        vm_offset_t     new_offset;
                    944:        vm_size_t       cluster_size;
                    945:        vm_offset_t     cluster_offset;         /* from memory_object start */
                    946:        vm_offset_t     cluster_lower_bound;    /* from vm_object_start */
                    947:        vm_offset_t     cluster_upper_bound;    /* from vm_object_start */
                    948:        vm_offset_t     cluster_start, cluster_end; /* from vm_object start */
                    949:        vm_offset_t     offset_within_cluster;
                    950:        vm_size_t       length_of_data;
                    951:        vm_page_t       friend, holding_page;
                    952:        vm_map_copy_t   copy;
                    953:        kern_return_t   rc;
                    954:        boolean_t       precious_clean = FALSE;
                    955:        int             pages_in_cluster;
                    956: 
                    957:        CLUSTER_STAT(int pages_at_higher_offsets = 0;)
                    958:        CLUSTER_STAT(int pages_at_lower_offsets = 0;)
                    959: 
                    960:        XPR(XPR_VM_PAGEOUT,
                    961:                "vm_pageout_cluster, object 0x%X offset 0x%X page 0x%X\n",
                    962:                (integer_t)object, offset, (integer_t)m, 0, 0);
                    963: 
                    964:        CLUSTER_STAT(vm_pageout_cluster_clusters++;)
                    965:        /*
                    966:         * Only a certain kind of page is appreciated here.
                    967:         */
                    968:        assert(m->busy && (m->dirty || m->precious) && (m->wire_count == 0));
                    969:        assert(!m->cleaning && !m->pageout && !m->inactive && !m->active);
                    970: 
                    971:        vm_object_lock(object);
                    972:        cluster_size = object->cluster_size;
                    973: 
                    974:        assert(cluster_size >= PAGE_SIZE);
                    975:        if (cluster_size < PAGE_SIZE) cluster_size = PAGE_SIZE;
                    976:        assert(object->pager_created && object->pager_initialized);
                    977:        assert(object->internal || object->pager_ready);
                    978: 
                    979:        if (m->precious && !m->dirty)
                    980:                precious_clean = TRUE;
                    981: 
                    982:        if (!object->pager_trusted || !allow_clustered_pageouts)
                    983:                cluster_size = PAGE_SIZE;
                    984:        vm_object_unlock(object);
                    985: 
                    986:        cluster_offset = paging_offset & (cluster_size - 1);
                    987:                        /* bytes from beginning of cluster */
                    988:        /* 
                    989:         * Due to unaligned mappings, we have to be careful
                    990:         * of negative offsets into the VM object. Clip the cluster 
                    991:         * boundary to the VM object, not the memory object.
                    992:         */
                    993:        if (offset > cluster_offset) {
                    994:                cluster_lower_bound = offset - cluster_offset;
                    995:                                                /* from vm_object */
                    996:        } else {
                    997:                cluster_lower_bound = 0;
                    998:        }
                    999:        cluster_upper_bound = (offset - cluster_offset) + cluster_size;
                   1000: 
                   1001:        /* set the page for future call to vm_fault_list_request */
                   1002:        holding_page = NULL;
                   1003:        vm_object_lock(m->object);
                   1004:        vm_page_lock_queues();
                   1005:        pmap_clear_modify(m->phys_addr);
                   1006:        m->dirty = TRUE;
                   1007:                m->busy = TRUE;
                   1008:                m->list_req_pending = TRUE;
                   1009:                m->cleaning = TRUE;
                   1010:        m->pageout = TRUE;
                   1011:        vm_page_wire(m);
                   1012:        vm_page_unlock_queues();
                   1013:        vm_object_unlock(m->object);
                   1014:        vm_pageout_throttle(m);
                   1015: 
                   1016:        /*
                   1017:         * Search backward for adjacent eligible pages to clean in 
                   1018:         * this operation.
                   1019:         */
                   1020: 
                   1021:        cluster_start = offset;
                   1022:        if (offset) {   /* avoid wrap-around at zero */
                   1023:            for (cluster_start = offset - PAGE_SIZE;
                   1024:                cluster_start >= cluster_lower_bound;
                   1025:                cluster_start -= PAGE_SIZE) {
                   1026:                assert(cluster_size > PAGE_SIZE);
                   1027: 
                   1028:                vm_object_lock(object);
                   1029:                vm_page_lock_queues();
                   1030: 
                   1031:                if ((friend = vm_pageout_cluster_page(object, cluster_start,
                   1032:                                precious_clean)) == VM_PAGE_NULL) {
                   1033:                        vm_page_unlock_queues();
                   1034:                        vm_object_unlock(object);
                   1035:                        break;
                   1036:                }
                   1037:                new_offset = (cluster_start + object->paging_offset)
                   1038:                                & (cluster_size - 1);
                   1039: 
                   1040:                assert(new_offset < cluster_offset);
                   1041:                pmap_clear_modify(m->phys_addr);
                   1042:                m->dirty = TRUE;
                   1043:                        m->list_req_pending = TRUE;
                   1044:                        m->cleaning = TRUE;
                   1045: /* do nothing except advance the write request, all we really need to */
                   1046: /* do is push the target page and let the code at the other end decide */
                   1047: /* what is really the right size */
                   1048:                if (vm_page_free_count <= vm_page_free_reserved) {
                   1049:                                m->busy = TRUE;
                   1050:                        m->pageout = TRUE;
                   1051:                        vm_page_wire(m);
                   1052:                }
                   1053: 
                   1054:                vm_page_unlock_queues();
                   1055:                vm_object_unlock(object);
                   1056:                CLUSTER_STAT(pages_at_lower_offsets++;)
                   1057: 
                   1058:            }
                   1059:            cluster_start += PAGE_SIZE;
                   1060:        }
                   1061:        assert(cluster_start >= cluster_lower_bound);
                   1062:        assert(cluster_start <= offset);
                   1063:        /*
                   1064:         * Search forward for adjacent eligible pages to clean in 
                   1065:         * this operation.
                   1066:         */
                   1067:        for (cluster_end = offset + PAGE_SIZE;
                   1068:                cluster_end < cluster_upper_bound;
                   1069:                cluster_end += PAGE_SIZE) {
                   1070:                assert(cluster_size > PAGE_SIZE);
                   1071: 
                   1072:                vm_object_lock(object);
                   1073:                vm_page_lock_queues();
                   1074: 
                   1075:                if ((friend = vm_pageout_cluster_page(object, cluster_end,
                   1076:                                precious_clean)) == VM_PAGE_NULL) {
                   1077:                        vm_page_unlock_queues();
                   1078:                        vm_object_unlock(object);
                   1079:                        break;
                   1080:                }
                   1081:                new_offset = (cluster_end + object->paging_offset)
                   1082:                                & (cluster_size - 1);
                   1083: 
                   1084:                assert(new_offset < cluster_size);
                   1085: 
                   1086:                pmap_clear_modify(m->phys_addr);
                   1087:                m->dirty = TRUE;
                   1088:                        m->list_req_pending = TRUE;
                   1089:                        m->cleaning = TRUE;
                   1090: /* do nothing except advance the write request, all we really need to */
                   1091: /* do is push the target page and let the code at the other end decide */
                   1092: /* what is really the right size */
                   1093:                if (vm_page_free_count <= vm_page_free_reserved) {
                   1094:                                m->busy = TRUE;
                   1095:                        m->pageout = TRUE;
                   1096:                        vm_page_wire(m);
                   1097:                }
                   1098: 
                   1099:                vm_page_unlock_queues();
                   1100:                vm_object_unlock(object);
                   1101:                CLUSTER_STAT(pages_at_higher_offsets++;)
                   1102:        }
                   1103:        assert(cluster_end <= cluster_upper_bound);
                   1104:        assert(cluster_end >= offset + PAGE_SIZE);
                   1105: 
                   1106:        /*
                   1107:         * (offset - cluster_offset) is beginning of cluster_object
                   1108:         * relative to vm_object start.
                   1109:         */
                   1110:        offset_within_cluster = cluster_start - (offset - cluster_offset);
                   1111:        length_of_data = cluster_end - cluster_start;
                   1112: 
                   1113:        assert(offset_within_cluster < cluster_size);
                   1114:        assert((offset_within_cluster + length_of_data) <= cluster_size);
                   1115: 
                   1116:        rc = KERN_SUCCESS;
                   1117:        assert(rc == KERN_SUCCESS);
                   1118: 
                   1119:        pages_in_cluster = length_of_data/PAGE_SIZE;
                   1120:        VM_STAT(pageouts++);
                   1121:        /* VM_STAT(pages_pagedout += pages_in_cluster); */
                   1122: 
                   1123: #if    MACH_CLUSTER_STATS
                   1124:        (cluster_stats[pages_at_lower_offsets].pages_at_lower_offsets)++;
                   1125:        (cluster_stats[pages_at_higher_offsets].pages_at_higher_offsets)++;
                   1126:        (cluster_stats[pages_in_cluster].pages_in_cluster)++;
                   1127: #endif /* MACH_CLUSTER_STATS */
                   1128: 
                   1129:        /*
                   1130:         * Send the data to the pager.
                   1131:         */
                   1132:        paging_offset = cluster_start + object->paging_offset;
                   1133: #ifdef MACH_BSD
                   1134:        if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) ==
                   1135:        ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1136:         rc = vnode_pager_data_return(object->pager,
                   1137:                                       object->pager_request,
                   1138:                                       paging_offset,
                   1139:                                       POINTER_T(copy),
                   1140:                                       length_of_data,
                   1141:                                       !precious_clean,
                   1142:                                       FALSE);
                   1143:        } else {
                   1144:                        rc = memory_object_data_return(object->pager,
                   1145:                                       object->pager_request,
                   1146:                                       paging_offset,
                   1147:                                       POINTER_T(copy),
                   1148:                                       length_of_data,
                   1149:                                       !precious_clean,
                   1150:                                       FALSE);
                   1151:        }
                   1152: #else
                   1153:        rc = memory_object_data_return(object->pager,
                   1154:                                       object->pager_request,
                   1155:                                       paging_offset,
                   1156:                                       POINTER_T(copy),
                   1157:                                       length_of_data,
                   1158:                                       !precious_clean,
                   1159:                                       FALSE);
                   1160: #endif
                   1161:        vm_object_paging_end(object);
                   1162: 
                   1163:        if (rc != KERN_SUCCESS)
                   1164:                vm_map_copy_discard(copy);
                   1165: 
                   1166:        if (holding_page) {
                   1167:                assert(!object->pager_trusted);
                   1168:                vm_object_lock(object);
                   1169:                VM_PAGE_FREE(holding_page);
                   1170:                vm_object_paging_end(object);
                   1171:                vm_object_unlock(object);
                   1172:        }
                   1173: }
                   1174: 
                   1175: /*
                   1176:  *     vm_pageout_return_write_pages
                   1177:  *     Recover pages from an aborted write attempt
                   1178:  *
                   1179:  */
                   1180: 
                   1181: vm_pageout_return_write_pages(
                   1182:        ipc_port_t control_port,  
                   1183:        vm_offset_t object_offset, 
                   1184:        vm_map_copy_t copy)
                   1185: {
                   1186:        vm_object_t     object;
                   1187:        int             offset;
                   1188:        int             size;
                   1189:        int             shadow_offset;
                   1190:        int             copy_offset;
                   1191:        int             j;
                   1192:        vm_page_t       m;
                   1193: 
                   1194: 
                   1195:        object = copy->cpy_object;
                   1196:        copy_offset = copy->offset;
                   1197:        size = copy->size;
                   1198: 
                   1199:        if((copy->type != VM_MAP_COPY_OBJECT) || (object->shadow == 0)) {
                   1200:                object = (vm_object_t)control_port->ip_kobject;
                   1201:                shadow_offset = (object_offset - object->paging_offset)
                   1202:                                                                 - copy->offset;
                   1203:        } else {
                   1204:                /* get the offset from the copy object */
                   1205:                shadow_offset = object->shadow_offset;
                   1206:                /* find the backing object */
                   1207:                object = object->shadow;
                   1208:        }
                   1209:        vm_object_lock(object);
                   1210: 
                   1211:        for(offset = 0, j=0; offset < size; offset+=page_size, j++) {
                   1212:                m = vm_page_lookup(object, 
                   1213:                                offset + shadow_offset + copy_offset);
                   1214:                if((m == VM_PAGE_NULL) || m->fictitious) {
                   1215: 
                   1216:                        vm_page_t       p;
                   1217:                        int             i;
                   1218:                        vm_object_t     copy_object;
                   1219: 
                   1220:                        /* m might be fictitious if the original page */
                   1221:                        /* was found to be in limbo at the time of    */
                   1222:                        /* vm_pageout_setup                           */
                   1223: 
                   1224:                        if((m != VM_PAGE_NULL) && m->fictitious) {
                   1225:                                m->cleaning = FALSE;
                   1226:                                vm_page_remove(m);
                   1227:                                /* if object is not pager trusted then       */
                   1228:                                /* this fictitious page will be removed      */
                   1229:                                /* as the holding page in vm_pageout_cluster */
                   1230:                                if (object->pager_trusted)
                   1231:                                        vm_page_free(m);
                   1232:                                if(vm_page_laundry_count)
                   1233:                                        vm_page_laundry_count--;
                   1234:                                if (vm_page_laundry_count 
                   1235:                                        < vm_page_laundry_min) {
                   1236:                                        vm_page_laundry_min = 0;
                   1237:                                        thread_wakeup((event_t) 
                   1238:                                                &vm_page_laundry_count);
                   1239:                                }
                   1240:                        }
                   1241:                        else if ((object->pager_trusted) &&
                   1242:                                        (copy->type == VM_MAP_COPY_OBJECT)) {
                   1243:                                vm_object_paging_end(object);
                   1244:                        }
                   1245: 
                   1246:                        copy_object = copy->cpy_object;
                   1247: 
                   1248:                        if(copy->type == VM_MAP_COPY_OBJECT) {
                   1249:                                p = (vm_page_t) queue_first(&copy_object->memq);
                   1250: 
                   1251:                                for(i = 0; 
                   1252:                                        i < copy_object->resident_page_count; 
                   1253:                                        i++) {
                   1254:                                        if(p->offset == (offset + copy_offset))
                   1255:                                                break;
                   1256:                                        p = (vm_page_t) queue_next(&p->listq);
                   1257:                                }
                   1258: 
                   1259:                                vm_page_remove(p);
                   1260:                        } else {
                   1261:                                p = copy->cpy_page_list[j];
                   1262:                                copy->cpy_page_list[j] = 0;
                   1263:                                p->gobbled = FALSE;
                   1264:                        }
                   1265: 
                   1266:                        vm_page_insert(p, object, 
                   1267:                                offset + shadow_offset + copy_offset);
                   1268:                        p->busy = TRUE;
                   1269:                        p->dirty = TRUE;
                   1270:                        p->laundry = FALSE;
                   1271:                        if (p->pageout) {
                   1272:                                p->pageout = FALSE;  /*dont throw away target*/
                   1273:                                vm_page_unwire(p);/* reactivates */
                   1274:                        }
                   1275:                } else if(m->pageout) {
                   1276:                        m->pageout = FALSE;  /* dont throw away target pages */
                   1277:                        vm_page_unwire(m);/* reactivates */
                   1278:                }
                   1279:        }
                   1280: 
                   1281:        vm_object_unlock(object);
                   1282:        vm_map_copy_discard(copy);
                   1283:        vm_object_lock(object);
                   1284: 
                   1285:        for(offset = 0; offset < size; offset+=page_size) { 
                   1286:                m = vm_page_lookup(object,
                   1287:                                offset + shadow_offset + copy_offset);
                   1288:                m->dirty = TRUE;  /* we'll send the pages home later */
                   1289:                m->busy = FALSE;  /* allow system access again */
                   1290:        }
                   1291: 
                   1292:        vm_object_unlock(object);
                   1293: }
                   1294: 
                   1295: /*
                   1296:  *     Trusted pager throttle.
                   1297:  *     Object must be unlocked, page queues must be unlocked.
                   1298:  */
                   1299: void
                   1300: vm_pageout_throttle(
                   1301:        register vm_page_t m)
                   1302: {
                   1303:        vm_page_lock_queues();
                   1304:        assert(!m->laundry);
                   1305:        m->laundry = TRUE;
                   1306:        while (vm_page_laundry_count >= vm_page_laundry_max) {
                   1307:                /*
                   1308:                 * Set the threshold for when vm_page_free()
                   1309:                 * should wake us up.
                   1310:                 */
                   1311:                vm_page_laundry_min = vm_page_laundry_max/2;
                   1312:                assert_wait((event_t) &vm_page_laundry_count, THREAD_UNINT);
                   1313:                vm_page_unlock_queues();
                   1314: 
                   1315:                /*
                   1316:                 * Pause to let the default pager catch up.
                   1317:                 */
                   1318:                thread_block((void (*)(void)) 0);
                   1319:                vm_page_lock_queues();
                   1320:        }
                   1321:        vm_page_laundry_count++;
                   1322:        vm_page_unlock_queues();
                   1323: }
                   1324: 
                   1325: /*
                   1326:  * The global variable vm_pageout_clean_active_pages controls whether
                   1327:  * active pages are considered valid to be cleaned in place during a
                   1328:  * clustered pageout. Performance measurements are necessary to determine
                   1329:  * the best policy.
                   1330:  */
                   1331: int vm_pageout_clean_active_pages = 1;
                   1332: /*
                   1333:  * vm_pageout_cluster_page: [Internal]
                   1334:  *
                   1335:  * return a vm_page_t to the page at (object,offset) if it is appropriate
                   1336:  * to clean in place. Pages that are non-existent, busy, absent, already
                   1337:  * cleaning, or not dirty are not eligible to be cleaned as an adjacent
                   1338:  * page in a cluster.
                   1339:  *
                   1340:  * The object must be locked on entry, and remains locked throughout
                   1341:  * this call.
                   1342:  */
                   1343: 
                   1344: vm_page_t
                   1345: vm_pageout_cluster_page(
                   1346:        vm_object_t object,
                   1347:        vm_offset_t offset,
                   1348:        boolean_t precious_clean)
                   1349: {
                   1350:        vm_page_t m;
                   1351: 
                   1352:        XPR(XPR_VM_PAGEOUT,
                   1353:                "vm_pageout_cluster_page, object 0x%X offset 0x%X\n",
                   1354:                (integer_t)object, offset, 0, 0, 0);
                   1355: 
                   1356:        if ((m = vm_page_lookup(object, offset)) == VM_PAGE_NULL)
                   1357:                return(VM_PAGE_NULL);
                   1358: 
                   1359:        if (m->busy || m->absent || m->cleaning || 
                   1360:            m->prep_pin_count != 0 ||
                   1361:            (m->wire_count != 0) || m->error)
                   1362:                return(VM_PAGE_NULL);
                   1363: 
                   1364:        if (vm_pageout_clean_active_pages) {
                   1365:                if (!m->active && !m->inactive) return(VM_PAGE_NULL);
                   1366:        } else {
                   1367:                if (!m->inactive) return(VM_PAGE_NULL);
                   1368:        }
                   1369: 
                   1370:        assert(!m->private);
                   1371:        assert(!m->fictitious);
                   1372: 
                   1373:        if (!m->dirty) m->dirty = pmap_is_modified(m->phys_addr);
                   1374: 
                   1375:        if (precious_clean) {
                   1376:                if (!m->precious || m->dirty)
                   1377:                        return(VM_PAGE_NULL);
                   1378:        } else {
                   1379:                if (!m->dirty)
                   1380:                        return(VM_PAGE_NULL);
                   1381:        }
                   1382:        return(m);
                   1383: }
                   1384: 
                   1385: /*
                   1386:  *     vm_pageout_scan does the dirty work for the pageout daemon.
                   1387:  *     It returns with vm_page_queue_free_lock held and
                   1388:  *     vm_page_free_wanted == 0.
                   1389:  */
                   1390: extern void vm_pageout_scan_continue(void);    /* forward; */
                   1391: 
                   1392: void
                   1393: vm_pageout_scan(void)
                   1394: {
                   1395:        unsigned int burst_count;
                   1396:        boolean_t now = FALSE;
                   1397:        unsigned int laundry_pages;
                   1398:        boolean_t need_more_inactive_pages;
                   1399:        unsigned int    loop_detect;
                   1400: 
                   1401:         XPR(XPR_VM_PAGEOUT, "vm_pageout_scan\n", 0, 0, 0, 0, 0);
                   1402: 
                   1403: /*???*/        /*
                   1404:         *      We want to gradually dribble pages from the active queue
                   1405:         *      to the inactive queue.  If we let the inactive queue get
                   1406:         *      very small, and then suddenly dump many pages into it,
                   1407:         *      those pages won't get a sufficient chance to be referenced
                   1408:         *      before we start taking them from the inactive queue.
                   1409:         *
                   1410:         *      We must limit the rate at which we send pages to the pagers.
                   1411:         *      data_write messages consume memory, for message buffers and
                   1412:         *      for map-copy objects.  If we get too far ahead of the pagers,
                   1413:         *      we can potentially run out of memory.
                   1414:         *
                   1415:         *      We can use the laundry count to limit directly the number
                   1416:         *      of pages outstanding to the default pager.  A similar
                   1417:         *      strategy for external pagers doesn't work, because
                   1418:         *      external pagers don't have to deallocate the pages sent them,
                   1419:         *      and because we might have to send pages to external pagers
                   1420:         *      even if they aren't processing writes.  So we also
                   1421:         *      use a burst count to limit writes to external pagers.
                   1422:         *
                   1423:         *      When memory is very tight, we can't rely on external pagers to
                   1424:         *      clean pages.  They probably aren't running, because they
                   1425:         *      aren't vm-privileged.  If we kept sending dirty pages to them,
                   1426:         *      we could exhaust the free list.  However, we can't just ignore
                   1427:         *      pages belonging to external objects, because there might be no
                   1428:         *      pages belonging to internal objects.  Hence, we get the page
                   1429:         *      into an internal object and then immediately double-page it,
                   1430:         *      sending it to the default pager.
                   1431:         *
                   1432:         *      consider_zone_gc should be last, because the other operations
                   1433:         *      might return memory to zones.
                   1434:         */
                   1435: 
                   1436:     Restart:
                   1437: 
                   1438:        mutex_lock(&vm_page_queue_free_lock);
                   1439:        now = (vm_page_free_count < vm_page_free_min);
                   1440:        mutex_unlock(&vm_page_queue_free_lock);
                   1441: #if    THREAD_SWAPPER
                   1442:        swapout_threads(now);
                   1443: #endif /* THREAD_SWAPPER */
                   1444: 
                   1445:        stack_collect();
                   1446:        consider_task_collect();
                   1447:        consider_thread_collect();
                   1448:        cleanup_limbo_queue();
                   1449:        consider_zone_gc();
                   1450:        consider_machine_collect();
                   1451: 
                   1452:        loop_detect = vm_page_active_count + vm_page_inactive_count;
                   1453: 
                   1454:        if (vm_page_free_count <= vm_page_free_reserved) {
                   1455:                need_more_inactive_pages = TRUE;
                   1456:        } else {
                   1457:                need_more_inactive_pages = FALSE;
                   1458:        }
                   1459:        for (burst_count = 0;;) {
                   1460:                register vm_page_t m;
                   1461:                register vm_object_t object;
                   1462:                unsigned int free_count;
                   1463: 
                   1464:                /*
                   1465:                 *      Recalculate vm_page_inactivate_target.
                   1466:                 */
                   1467: 
                   1468:                vm_page_lock_queues();
                   1469:                vm_page_inactive_target =
                   1470:                        VM_PAGE_INACTIVE_TARGET(vm_page_active_count +
                   1471:                                                vm_page_inactive_count);
                   1472: 
                   1473:                /*
                   1474:                 *      Move pages from active to inactive.
                   1475:                 */
                   1476: 
                   1477:                while ((vm_page_inactive_count < vm_page_inactive_target ||
                   1478:                        need_more_inactive_pages) &&
                   1479:                       !queue_empty(&vm_page_queue_active)) {
                   1480:                        register vm_object_t object;
                   1481: 
                   1482:                        vm_pageout_active++;
                   1483:                        m = (vm_page_t) queue_first(&vm_page_queue_active);
                   1484: 
                   1485:                        /*
                   1486:                         * If we're getting really low on memory,
                   1487:                         * try selecting a page that will go 
                   1488:                         * directly to the default_pager.
                   1489:                         * If there are no such pages, we have to
                   1490:                         * page out a page backed by an EMM,
                   1491:                         * so that the default_pager can recover
                   1492:                         * it eventually.
                   1493:                         */
                   1494:                        if (need_more_inactive_pages && 
                   1495:                                (IP_VALID(memory_manager_default))) {
                   1496:                                vm_pageout_scan_active_emm_throttle++;
                   1497:                                do {
                   1498:                                        assert(m->active && !m->inactive);
                   1499:                                        object = m->object;
                   1500: 
                   1501:                                        if (vm_object_lock_try(object)) {
                   1502:                                                if (object->pager_trusted ||
                   1503:                                                    object->internal) {
                   1504:                                                        /* found one ! */
                   1505:                                                        vm_pageout_scan_active_emm_throttle_success++;
                   1506:                                                        goto object_locked_active;
                   1507:                                                }
                   1508:                                                vm_object_unlock(object);
                   1509:                                        }
                   1510:                                        m = (vm_page_t) queue_next(&m->pageq);
                   1511:                                } while (!queue_end(&vm_page_queue_active,
                   1512:                                                    (queue_entry_t) m));
                   1513:                                if (queue_end(&vm_page_queue_active,
                   1514:                                              (queue_entry_t) m)) {
                   1515:                                        vm_pageout_scan_active_emm_throttle_failure++;
                   1516:                                        m = (vm_page_t)
                   1517:                                                queue_first(&vm_page_queue_active);
                   1518:                                }
                   1519:                        }
                   1520: 
                   1521:                        assert(m->active && !m->inactive);
                   1522: 
                   1523:                        object = m->object;
                   1524:                        if (!vm_object_lock_try(object)) {
                   1525:                                /*
                   1526:                                 *      Move page to end and continue.
                   1527:                                 */
                   1528: 
                   1529:                                queue_remove(&vm_page_queue_active, m,
                   1530:                                             vm_page_t, pageq);
                   1531:                                queue_enter(&vm_page_queue_active, m,
                   1532:                                            vm_page_t, pageq);
                   1533:                                vm_page_unlock_queues();
                   1534:                                mutex_pause();
                   1535:                                vm_page_lock_queues();
                   1536:                                continue;
                   1537:                        }
                   1538: 
                   1539:                    object_locked_active:
                   1540:                        /*
                   1541:                         *      If the page is busy, then we pull it
                   1542:                         *      off the active queue and leave it alone.
                   1543:                         */
                   1544: 
                   1545:                        if (m->busy) {
                   1546:                                vm_object_unlock(object);
                   1547:                                queue_remove(&vm_page_queue_active, m,
                   1548:                                             vm_page_t, pageq);
                   1549:                                m->active = FALSE;
                   1550:                                if (!m->fictitious)
                   1551:                                        vm_page_active_count--;
                   1552:                                continue;
                   1553:                        }
                   1554: 
                   1555:                        /*
                   1556:                         *      Deactivate the page while holding the object
                   1557:                         *      locked, so we know the page is still not busy.
                   1558:                         *      This should prevent races between pmap_enter
                   1559:                         *      and pmap_clear_reference.  The page might be
                   1560:                         *      absent or fictitious, but vm_page_deactivate
                   1561:                         *      can handle that.
                   1562:                         */
                   1563: 
                   1564:                        vm_page_deactivate(m);
                   1565:                        vm_object_unlock(object);
                   1566:                }
                   1567: 
                   1568:                /*
                   1569:                 *      We are done if we have met our target *and*
                   1570:                 *      nobody is still waiting for a page.
                   1571:                 */
                   1572: 
                   1573:                mutex_lock(&vm_page_queue_free_lock);
                   1574:                free_count = vm_page_free_count;
                   1575:                if ((free_count >= vm_page_free_target) &&
                   1576:                    (vm_page_free_wanted == 0)) {
                   1577:                        vm_page_unlock_queues();
                   1578:                        break;
                   1579:                }
                   1580:                mutex_unlock(&vm_page_queue_free_lock);
                   1581: 
                   1582:                /*
                   1583:                 * Sometimes we have to pause:
                   1584:                 *      1) No inactive pages - nothing to do.
                   1585:                 *      2) Flow control - wait for untrusted pagers to catch up.
                   1586:                 */
                   1587: 
                   1588:                if (queue_empty(&vm_page_queue_inactive) ||
                   1589:                    ((--loop_detect) == 0)      ||
                   1590:                    (burst_count >= vm_pageout_burst_max)) {
                   1591:                        unsigned int pages, msecs;
                   1592: 
                   1593:                        /*
                   1594:                         *      vm_pageout_burst_wait is msecs/page.
                   1595:                         *      If there is nothing for us to do, we wait
                   1596:                         *      at least vm_pageout_empty_wait msecs.
                   1597:                         */
                   1598:                        pages = burst_count;
                   1599:        
                   1600:                        if (loop_detect == 0) {
                   1601:                                printf("Warning: No physical memory suitable for pageout or reclaim, pageout thread temporarily going to sleep\n");
                   1602:                                msecs = vm_free_page_pause;
                   1603:                        }
                   1604:                        else {
                   1605:                                msecs = burst_count * vm_pageout_burst_wait;
                   1606:                        }
                   1607: 
                   1608:                        if (queue_empty(&vm_page_queue_inactive) &&
                   1609:                            (msecs < vm_pageout_empty_wait))
                   1610:                                msecs = vm_pageout_empty_wait;
                   1611:                        vm_page_unlock_queues();
                   1612:                        assert_wait_timeout(msecs, THREAD_INTERRUPTIBLE);
                   1613:                        counter(c_vm_pageout_scan_block++);
                   1614: 
                   1615:                        /*
                   1616:                         *      Unfortunately, we don't have call_continuation
                   1617:                         *      so we can't rely on tail-recursion.
                   1618:                         */
                   1619:                        thread_block((void (*)(void)) 0);
                   1620:                        thread_cancel_timer();
                   1621:                        vm_pageout_scan_continue();
                   1622:                        goto Restart;
                   1623:                        /*NOTREACHED*/
                   1624:                }
                   1625: 
                   1626:                vm_pageout_inactive++;
                   1627:                m = (vm_page_t) queue_first(&vm_page_queue_inactive);
                   1628: 
                   1629:                if ((vm_page_free_count <= vm_page_free_reserved) && 
                   1630:                                (IP_VALID(memory_manager_default))) {
                   1631:                        /*
                   1632:                         * We're really low on memory. Try to select a page that
                   1633:                         * would go directly to the default_pager.
                   1634:                         * If there are no such pages, we have to page out a 
                   1635:                         * page backed by an EMM, so that the default_pager
                   1636:                         * can recover it eventually.
                   1637:                         */
                   1638:                        vm_pageout_scan_inactive_emm_throttle++;
                   1639:                        do {
                   1640:                                assert(!m->active && m->inactive);
                   1641:                                object = m->object;
                   1642: 
                   1643:                                if (vm_object_lock_try(object)) {
                   1644:                                        if (object->pager_trusted ||
                   1645:                                            object->internal) {
                   1646:                                                /* found one ! */
                   1647:                                                vm_pageout_scan_inactive_emm_throttle_success++;
                   1648:                                                goto object_locked_inactive;
                   1649:                                        }
                   1650:                                        vm_object_unlock(object);
                   1651:                                }
                   1652:                                m = (vm_page_t) queue_next(&m->pageq);
                   1653:                        } while (!queue_end(&vm_page_queue_inactive,
                   1654:                                            (queue_entry_t) m));
                   1655:                        if (queue_end(&vm_page_queue_inactive,
                   1656:                                      (queue_entry_t) m)) {
                   1657:                                vm_pageout_scan_inactive_emm_throttle_failure++;
                   1658:                                /*
                   1659:                                 * We should check the "active" queue
                   1660:                                 * for good candidates to page out.
                   1661:                                 */
                   1662:                                need_more_inactive_pages = TRUE;
                   1663: 
                   1664:                                m = (vm_page_t)
                   1665:                                        queue_first(&vm_page_queue_inactive);
                   1666:                        }
                   1667:                }
                   1668: 
                   1669:                assert(!m->active && m->inactive);
                   1670:                object = m->object;
                   1671: 
                   1672:                /*
                   1673:                 *      Try to lock object; since we've got the
                   1674:                 *      page queues lock, we can only try for this one.
                   1675:                 */
                   1676: 
                   1677:                if (!vm_object_lock_try(object)) {
                   1678:                        /*
                   1679:                         *      Move page to end and continue.
                   1680:                         */
                   1681:                        queue_remove(&vm_page_queue_inactive, m,
                   1682:                                     vm_page_t, pageq);
                   1683:                        queue_enter(&vm_page_queue_inactive, m,
                   1684:                                    vm_page_t, pageq);
                   1685:                        vm_page_unlock_queues();
                   1686:                        mutex_pause();
                   1687:                        vm_pageout_inactive_nolock++;
                   1688:                        continue;
                   1689:                }
                   1690: 
                   1691:            object_locked_inactive:
                   1692:                /*
                   1693:                 *      Paging out pages of objects which pager is being
                   1694:                 *      created by another thread must be avoided, because
                   1695:                 *      this thread may claim for memory, thus leading to a
                   1696:                 *      possible dead lock between it and the pageout thread
                   1697:                 *      which will wait for pager creation, if such pages are
                   1698:                 *      finally chosen. The remaining assumption is that there
                   1699:                 *      will finally be enough available pages in the inactive
                   1700:                 *      pool to page out in order to satisfy all memory claimed
                   1701:                 *      by the thread which concurrently creates the pager.
                   1702:                 */
                   1703: 
                   1704:                if (!object->pager_initialized && object->pager_created) {
                   1705:                        /*
                   1706:                         *      Move page to end and continue, hoping that
                   1707:                         *      there will be enough other inactive pages to
                   1708:                         *      page out so that the thread which currently
                   1709:                         *      initializes the pager will succeed.
                   1710:                         */
                   1711:                        queue_remove(&vm_page_queue_inactive, m,
                   1712:                                     vm_page_t, pageq);
                   1713:                        queue_enter(&vm_page_queue_inactive, m,
                   1714:                                    vm_page_t, pageq);
                   1715:                        vm_page_unlock_queues();
                   1716:                        vm_object_unlock(object);
                   1717:                        vm_pageout_inactive_avoid++;
                   1718:                        continue;
                   1719:                }
                   1720: 
                   1721:                /*
                   1722:                 *      Remove the page from the inactive list.
                   1723:                 */
                   1724: 
                   1725:                queue_remove(&vm_page_queue_inactive, m, vm_page_t, pageq);
                   1726:                m->inactive = FALSE;
                   1727:                if (!m->fictitious)
                   1728:                        vm_page_inactive_count--;
                   1729: 
                   1730:                if (m->busy || !object->alive) {
                   1731:                        /*
                   1732:                         *      Somebody is already playing with this page.
                   1733:                         *      Leave it off the pageout queues.
                   1734:                         */
                   1735: 
                   1736:                        vm_page_unlock_queues();
                   1737:                        vm_object_unlock(object);
                   1738:                        vm_pageout_inactive_busy++;
                   1739:                        continue;
                   1740:                }
                   1741: 
                   1742:                /*
                   1743:                 *      If it's absent or in error, we can reclaim the page.
                   1744:                 */
                   1745: 
                   1746:                if (m->absent || m->error) {
                   1747:                        vm_pageout_inactive_absent++;
                   1748:                    reclaim_page:
                   1749:                        vm_page_free(m);
                   1750:                        vm_page_unlock_queues();
                   1751:                        vm_object_unlock(object);
                   1752:                        continue;
                   1753:                }
                   1754: 
                   1755:                assert(!m->private);
                   1756:                assert(!m->fictitious);
                   1757: 
                   1758:                /*
                   1759:                 *      If already cleaning this page in place, convert from
                   1760:                 *      "adjacent" to "target". We can leave the page mapped,
                   1761:                 *      and vm_pageout_object_terminate will determine whether
                   1762:                 *      to free or reactivate.
                   1763:                 */
                   1764: 
                   1765:                if (m->cleaning) {
                   1766: #if    MACH_CLUSTER_STATS
                   1767:                        vm_pageout_cluster_conversions++;
                   1768: #endif
                   1769:                        if (m->prep_pin_count == 0) {
                   1770:                                m->busy = TRUE;
                   1771:                                m->pageout = TRUE;
                   1772:                                vm_page_wire(m);
                   1773:                        }
                   1774:                        vm_object_unlock(object);
                   1775:                        vm_page_unlock_queues();
                   1776:                        continue;
                   1777:                }
                   1778: 
                   1779:                /*
                   1780:                 *      If it's being used, reactivate.
                   1781:                 *      (Fictitious pages are either busy or absent.)
                   1782:                 */
                   1783: 
                   1784:                if (m->reference || pmap_is_referenced(m->phys_addr)) {
                   1785:                        vm_pageout_inactive_used++;
                   1786:                    reactivate_page:
                   1787: #if    ADVISORY_PAGEOUT
                   1788:                        if (m->discard_request) {
                   1789:                                m->discard_request = FALSE;
                   1790:                        }
                   1791: #endif /* ADVISORY_PAGEOUT */
                   1792:                        vm_object_unlock(object);
                   1793:                        vm_page_activate(m);
                   1794:                        VM_STAT(reactivations++);
                   1795:                        vm_page_unlock_queues();
                   1796:                        continue;
                   1797:                }
                   1798: 
                   1799:                if (m->prep_pin_count != 0) {
                   1800:                        boolean_t pinned = FALSE;
                   1801: 
                   1802:                        vm_page_pin_lock();
                   1803:                        if (m->pin_count != 0) {
                   1804:                                /* skip and reactivate pinned page */
                   1805:                                pinned = TRUE;
                   1806:                                vm_pageout_inactive_pinned++;
                   1807:                        } else {
                   1808:                                /* page is prepped; send it into limbo */
                   1809:                                m->limbo = TRUE;
                   1810:                                vm_pageout_inactive_limbo++;
                   1811:                        }
                   1812:                        vm_page_pin_unlock();
                   1813:                        if (pinned)
                   1814:                                goto reactivate_page;
                   1815:                }
                   1816: 
                   1817: #if    ADVISORY_PAGEOUT
                   1818:                if (object->advisory_pageout) {
                   1819:                        boolean_t       do_throttle;
                   1820:                        ipc_port_t      port;
                   1821:                        vm_offset_t     discard_offset;
                   1822: 
                   1823:                        if (m->discard_request) {
                   1824:                                vm_stat_discard_failure++;
                   1825:                                goto mandatory_pageout;
                   1826:                        }
                   1827: 
                   1828:                        assert(object->pager_initialized);
                   1829:                        m->discard_request = TRUE;
                   1830:                        port = object->pager;
                   1831: 
                   1832:                        /* system-wide throttle */
                   1833:                        do_throttle = (vm_page_free_count <=
                   1834:                                       vm_page_free_reserved);
                   1835:                        if (!do_throttle) {
                   1836:                                /* throttle on this pager */
                   1837:                                /* XXX lock ordering ? */
                   1838:                                ip_lock(port);
                   1839:                                do_throttle= imq_full(&port->ip_messages);
                   1840:                                ip_unlock(port);
                   1841:                        }
                   1842:                        if (do_throttle) {
                   1843:                                vm_stat_discard_throttle++;
                   1844: #if 0
                   1845:                                /* ignore this page and skip to next */
                   1846:                                vm_page_unlock_queues();
                   1847:                                vm_object_unlock(object);
                   1848:                                continue;
                   1849: #else
                   1850:                                /* force mandatory pageout */
                   1851:                                goto mandatory_pageout;
                   1852: #endif
                   1853:                        }
                   1854: 
                   1855:                        /* proceed with discard_request */
                   1856:                        vm_page_activate(m);
                   1857:                        vm_stat_discard++;
                   1858:                        VM_STAT(reactivations++);
                   1859:                        discard_offset = m->offset + object->paging_offset;
                   1860:                        vm_stat_discard_sent++;
                   1861:                        vm_page_unlock_queues();
                   1862:                        vm_object_unlock(object);
                   1863:                        memory_object_discard_request(object->pager,
                   1864:                                                      object->pager_request,
                   1865:                                                      discard_offset,
                   1866:                                                      PAGE_SIZE);
                   1867:                        continue;
                   1868:                }
                   1869:        mandatory_pageout:
                   1870: #endif /* ADVISORY_PAGEOUT */
                   1871:                        
                   1872:                 XPR(XPR_VM_PAGEOUT,
                   1873:                 "vm_pageout_scan, replace object 0x%X offset 0x%X page 0x%X\n",
                   1874:                 (integer_t)object, (integer_t)m->offset, (integer_t)m, 0,0);
                   1875: 
                   1876:                /*
                   1877:                 *      Eliminate all mappings.
                   1878:                 */
                   1879: 
                   1880:                m->busy = TRUE;
                   1881:                pmap_page_protect(m->phys_addr, VM_PROT_NONE);
                   1882:                if (!m->dirty)
                   1883:                        m->dirty = pmap_is_modified(m->phys_addr);
                   1884: 
                   1885:                /*
                   1886:                 *      If it's clean and not precious, we can free the page.
                   1887:                 */
                   1888: 
                   1889:                if (!m->dirty && !m->precious) {
                   1890:                        vm_pageout_inactive_clean++;
                   1891:                        goto reclaim_page;
                   1892:                }
                   1893:                vm_page_unlock_queues();
                   1894: 
                   1895:                /*
                   1896:                 *      If there is no memory object for the page, create
                   1897:                 *      one and hand it to the default pager.
                   1898:                 *      [First try to collapse, so we don't create
                   1899:                 *      one unnecessarily.]
                   1900:                 */
                   1901: 
                   1902:                if (!object->pager_initialized)
                   1903:                        vm_object_collapse(object);
                   1904:                if (!object->pager_initialized)
                   1905:                        vm_object_pager_create(object);
                   1906:                if (!object->pager_initialized) {
                   1907:                        /*
                   1908:                         *      Still no pager for the object.
                   1909:                         *      Reactivate the page.
                   1910:                         *
                   1911:                         *      Should only happen if there is no
                   1912:                         *      default pager.
                   1913:                         */
                   1914:                        vm_page_lock_queues();
                   1915:                        vm_page_activate(m);
                   1916:                        vm_page_unlock_queues();
                   1917: 
                   1918:                        /*
                   1919:                         *      And we are done with it.
                   1920:                         */
                   1921:                        PAGE_WAKEUP_DONE(m);
                   1922:                        vm_object_unlock(object);
                   1923: 
                   1924:                        /*
                   1925:                         * break here to get back to the preemption
                   1926:                         * point in the outer loop so that we don't
                   1927:                         * spin forever if there is no default pager.
                   1928:                         */
                   1929:                        vm_pageout_dirty_no_pager++;
                   1930:                        /*
                   1931:                         * Well there's no pager, but we can still reclaim
                   1932:                         * free pages out of the inactive list.  Go back
                   1933:                         * to top of loop and look for suitable pages.
                   1934:                         */
                   1935:                        continue;
                   1936:                }
                   1937: 
                   1938:                if (object->pager_initialized && object->pager == IP_NULL) {
                   1939:                        /*
                   1940:                         * This pager has been destroyed by either
                   1941:                         * memory_object_destroy or vm_object_destroy, and
                   1942:                         * so there is nowhere for the page to go.
                   1943:                         * Just free the page.
                   1944:                         */
                   1945:                        VM_PAGE_FREE(m);
                   1946:                        vm_object_unlock(object);
                   1947:                        continue;
                   1948:                }
                   1949: 
                   1950:                vm_pageout_inactive_dirty++;
                   1951:                if (!object->internal)
                   1952:                        burst_count++;
                   1953:                vm_object_paging_begin(object);
                   1954:                vm_object_unlock(object);
                   1955:                vm_pageout_cluster(m);  /* flush it */
                   1956:        }
                   1957: }
                   1958: 
                   1959: counter(unsigned int   c_vm_pageout_scan_continue = 0;)
                   1960: 
                   1961: void
                   1962: vm_pageout_scan_continue(void)
                   1963: {
                   1964:        /*
                   1965:         *      We just paused to let the pagers catch up.
                   1966:         *      If vm_page_laundry_count is still high,
                   1967:         *      then we aren't waiting long enough.
                   1968:         *      If we have paused some vm_pageout_pause_max times without
                   1969:         *      adjusting vm_pageout_burst_wait, it might be too big,
                   1970:         *      so we decrease it.
                   1971:         */
                   1972: 
                   1973:        vm_page_lock_queues();
                   1974:        counter(++c_vm_pageout_scan_continue);
                   1975:        if (vm_page_laundry_count > vm_pageout_burst_min) {
                   1976:                vm_pageout_burst_wait++;
                   1977:                vm_pageout_pause_count = 0;
                   1978:        } else if (++vm_pageout_pause_count > vm_pageout_pause_max) {
                   1979:                vm_pageout_burst_wait = (vm_pageout_burst_wait * 3) / 4;
                   1980:                if (vm_pageout_burst_wait < 1)
                   1981:                        vm_pageout_burst_wait = 1;
                   1982:                vm_pageout_pause_count = 0;
                   1983:        }
                   1984:        vm_page_unlock_queues();
                   1985: }
                   1986: 
                   1987: void vm_page_free_reserve(int pages);
                   1988: int vm_page_free_count_init;
                   1989: 
                   1990: void
                   1991: vm_page_free_reserve(
                   1992:        int pages)
                   1993: {
                   1994:        int             free_after_reserve;
                   1995: 
                   1996:        vm_page_free_reserved += pages;
                   1997: 
                   1998:        free_after_reserve = vm_page_free_count_init - vm_page_free_reserved;
                   1999: 
                   2000:        vm_page_free_min = vm_page_free_reserved +
                   2001:                VM_PAGE_FREE_MIN(free_after_reserve);
                   2002: 
                   2003:        vm_page_free_target = vm_page_free_reserved +
                   2004:                VM_PAGE_FREE_TARGET(free_after_reserve);
                   2005: 
                   2006:        if (vm_page_free_target < vm_page_free_min + 5)
                   2007:                vm_page_free_target = vm_page_free_min + 5;
                   2008: }
                   2009: 
                   2010: /*
                   2011:  *     vm_pageout is the high level pageout daemon.
                   2012:  */
                   2013: 
                   2014: 
                   2015: void
                   2016: vm_pageout(void)
                   2017: {
                   2018:        thread_t        thread;
                   2019:        processor_set_t pset;
                   2020:         kern_return_t                   ret;
                   2021:         policy_base_t                   base;
                   2022:         policy_limit_t                  limit;
                   2023:         policy_fifo_base_data_t         fifo_base;
                   2024:         policy_fifo_limit_data_t        fifo_limit;
                   2025: 
                   2026:         /*
                   2027:          * Set thread privileges.
                   2028:          */
                   2029:        thread = current_thread();
                   2030:         thread->vm_privilege = TRUE;
                   2031:         stack_privilege(thread);
                   2032:        thread_swappable(current_act(), FALSE);
                   2033: 
                   2034:        /*
                   2035:         * Set thread scheduling priority and policy.
                   2036:         */
                   2037:        pset = thread->processor_set;
                   2038:         base = (policy_base_t) &fifo_base;
                   2039:         limit = (policy_limit_t) &fifo_limit;
                   2040:         fifo_base.base_priority = BASEPRI_SYSTEM;
                   2041:         fifo_limit.max_priority = BASEPRI_SYSTEM;
                   2042:         ret = thread_set_policy(thread->top_act, pset, POLICY_FIFO, 
                   2043:                                base, POLICY_TIMESHARE_BASE_COUNT, 
                   2044:                                limit, POLICY_TIMESHARE_LIMIT_COUNT);
                   2045:         if (ret != KERN_SUCCESS)
                   2046:                 printf("WARNING: vm_pageout_thread is being TIMESHARED!\n");
                   2047: 
                   2048:        /*
                   2049:         *      Initialize some paging parameters.
                   2050:         */
                   2051: 
                   2052:        if (vm_page_laundry_max == 0)
                   2053:                vm_page_laundry_max = VM_PAGE_LAUNDRY_MAX;
                   2054: 
                   2055:        if (vm_pageout_burst_max == 0)
                   2056:                vm_pageout_burst_max = VM_PAGEOUT_BURST_MAX;
                   2057: 
                   2058:        if (vm_pageout_burst_wait == 0)
                   2059:                vm_pageout_burst_wait = VM_PAGEOUT_BURST_WAIT;
                   2060: 
                   2061:        if (vm_pageout_empty_wait == 0)
                   2062:                vm_pageout_empty_wait = VM_PAGEOUT_EMPTY_WAIT;
                   2063: 
                   2064:        vm_page_free_count_init = vm_page_free_count;
                   2065:        /*
                   2066:         * even if we've already called vm_page_free_reserve
                   2067:         * call it again here to insure that the targets are
                   2068:         * accurately calculated (it uses vm_page_free_count_init)
                   2069:         * calling it with an arg of 0 will not change the reserve
                   2070:         * but will re-calculate free_min and free_target
                   2071:         */
                   2072:        if (vm_page_free_reserved < VM_PAGE_FREE_RESERVED)
                   2073:                vm_page_free_reserve(VM_PAGE_FREE_RESERVED - vm_page_free_reserved);
                   2074:        else
                   2075:                vm_page_free_reserve(0);
                   2076: 
                   2077:        /*
                   2078:         *      vm_pageout_scan will set vm_page_inactive_target.
                   2079:         *
                   2080:         *      The pageout daemon is never done, so loop forever.
                   2081:         *      We should call vm_pageout_scan at least once each
                   2082:         *      time we are woken, even if vm_page_free_wanted is
                   2083:         *      zero, to check vm_page_free_target and
                   2084:         *      vm_page_inactive_target.
                   2085:         */
                   2086:        for (;;) {
                   2087:                vm_pageout_scan();
                   2088:                /* we hold vm_page_queue_free_lock now */
                   2089:                assert(vm_page_free_wanted == 0);
                   2090:                assert_wait((event_t) &vm_page_free_wanted, THREAD_UNINT);
                   2091:                mutex_unlock(&vm_page_queue_free_lock);
                   2092:                counter(c_vm_pageout_block++);
                   2093:                thread_block((void (*)(void)) 0);
                   2094:        }
                   2095:        /*NOTREACHED*/
                   2096: }
                   2097: 
                   2098: 
                   2099: 
                   2100: /*  
                   2101:  *     Routine:        vm_fault_list_request
                   2102:  *     Purpose:        
                   2103:  *             Cause the population of a portion of a vm_object.
                   2104:  *             Depending on the nature of the request, the pages
                   2105:  *             returned may be contain valid data or be uninitialized.
                   2106:  *             A page list structure, listing the physical pages
                   2107:  *             will be returned upon request.
                   2108:  *             This function is called by the file system or any other
                   2109:  *             supplier of backing store to a pager.
                   2110:  *             IMPORTANT NOTE: The caller must still respect the relationship
                   2111:  *             between the vm_object and its backing memory object.  The
                   2112:  *             caller MUST NOT substitute changes in the backing file
                   2113:  *             without first doing a memory_object_lock_request on the 
                   2114:  *             target range unless it is know that the pages are not
                   2115:  *             shared with another entity at the pager level.
                   2116:  *             Copy_in_to:
                   2117:  *                     if a page list structure is present
                   2118:  *                     return the mapped physical pages, where a
                   2119:  *                     page is not present, return a non-initialized
                   2120:  *                     one.  If the no_sync bit is turned on, don't
                   2121:  *                     call the pager unlock to synchronize with other
                   2122:  *                     possible copies of the page. Leave pages busy
                   2123:  *                     in the original object, if a page list structure
                   2124:  *                     was specified.  When a commit of the page list
                   2125:  *                     pages is done, the dirty bit will be set for each one.
                   2126:  *             Copy_out_from:
                   2127:  *                     If a page list structure is present, return
                   2128:  *                     all mapped pages.  Where a page does not exist
                   2129:  *                     map a zero filled one. Leave pages busy in
                   2130:  *                     the original object.  If a page list structure
                   2131:  *                     is not specified, this call is a no-op. 
                   2132:  *
                   2133:  *             Note:  access of default pager objects has a rather interesting
                   2134:  *             twist.  The caller of this routine, presumably the file system
                   2135:  *             page cache handling code, will never actually make a request
                   2136:  *             against a default pager backed object.  Only the default
                   2137:  *             pager will make requests on backing store related vm_objects
                   2138:  *             In this way the default pager can maintain the relationship
                   2139:  *             between backing store files (abstract memory objects) and 
                   2140:  *             the vm_objects (cache objects), they support.
                   2141:  *
                   2142:  */
                   2143: kern_return_t
                   2144: vm_fault_list_request(
                   2145:        vm_object_t             object,
                   2146:        vm_object_offset_t      offset,
                   2147:        vm_size_t               size,
                   2148:        upl_t                   *upl_ptr,
                   2149:        upl_page_info_t         **user_page_list_ptr,
                   2150:        int                     page_list_count,
                   2151:        int                     cntrl_flags)
                   2152: {
                   2153:        vm_page_t               dst_page;
                   2154:        vm_object_offset_t      dst_offset = offset;
                   2155:        upl_page_info_t         *user_page_list;
                   2156:        vm_size_t               xfer_size = size;
                   2157:        boolean_t               do_m_lock = FALSE;
                   2158:        boolean_t               dirty;
                   2159:        upl_t                   upl = NULL;
                   2160:        int                     entry;
                   2161: 
                   2162:        if(cntrl_flags & UPL_SET_INTERNAL)
                   2163:                page_list_count = 20;
                   2164:        if(user_page_list_ptr && (page_list_count < (size/page_size)))
                   2165:                return KERN_INVALID_ARGUMENT;
                   2166: 
                   2167:        if((!object->internal) && (object->paging_offset != 0))
                   2168:                panic("vm_fault_list_request: vnode object with non-zero paging offset\n");
                   2169: 
                   2170:        if((cntrl_flags & UPL_COPYOUT_FROM) && (upl_ptr == NULL)) {
                   2171:                return KERN_SUCCESS;
                   2172:        }
                   2173:        if(upl_ptr) {
                   2174:                if(cntrl_flags & UPL_SET_INTERNAL) {
                   2175:                        upl = upl_create(TRUE);
                   2176:                        user_page_list = (upl_page_info_t *)
                   2177:                                (((vm_offset_t)upl) + sizeof(struct upl));
                   2178:                        if(user_page_list_ptr)
                   2179:                                *user_page_list_ptr = user_page_list;
                   2180:                        else
                   2181:                                user_page_list = NULL;
                   2182:                        upl->flags |= UPL_INTERNAL;
                   2183:                } else {
                   2184:                        upl = upl_create(FALSE);
                   2185:                        if(user_page_list_ptr)
                   2186:                                user_page_list = *user_page_list_ptr;
                   2187:                        else
                   2188:                                user_page_list = NULL;
                   2189:                }
                   2190:                upl->map_object = vm_object_allocate(size);
                   2191:                vm_object_lock(upl->map_object);
                   2192:                upl->map_object->shadow = object;
                   2193:                upl->size = size;
                   2194:                upl->offset = offset + object->paging_offset;
                   2195:                upl->map_object->pageout = TRUE;
                   2196:                upl->map_object->can_persist = FALSE;
                   2197:                upl->map_object->copy_strategy = MEMORY_OBJECT_COPY_NONE;
                   2198:                upl->map_object->shadow_offset = offset;
                   2199:                vm_object_unlock(upl->map_object);
                   2200:                *upl_ptr = upl;
                   2201:        }
                   2202:        vm_object_lock(object);
                   2203:        vm_object_paging_begin(object);
                   2204:        entry = 0;
                   2205:        if(cntrl_flags & UPL_COPYOUT_FROM) {
                   2206:                while (xfer_size) {     
                   2207:                        vm_page_t       alias_page;
                   2208:                        
                   2209:                        if(((dst_page = vm_page_lookup(object, 
                   2210:                                dst_offset)) == VM_PAGE_NULL) ||
                   2211:                                dst_page->fictitious ||
                   2212:                                dst_page->absent ||
                   2213:                                dst_page->error ||
                   2214:                                (dst_page->wire_count != 0 && 
                   2215:                                                        !dst_page->pageout) ||
                   2216:                                ((!(dst_page->dirty || dst_page->precious)) &&
                   2217:                                (cntrl_flags & UPL_RET_ONLY_DIRTY))) {
                   2218:                                if(user_page_list)
                   2219:                                        user_page_list[entry].phys_addr = 0;
                   2220:                        } else {
                   2221:                                
                   2222:                                if(dst_page->busy && 
                   2223:                                        (!(dst_page->list_req_pending && 
                   2224:                                                dst_page->pageout))) {
                   2225:                                        if(cntrl_flags & UPL_NOBLOCK) {
                   2226:                                                if(user_page_list)
                   2227:                                                        user_page_list[entry]
                   2228:                                                                .phys_addr = 0;
                   2229:                                                entry++;
                   2230:                                                dst_offset += PAGE_SIZE;
                   2231:                                                xfer_size -= PAGE_SIZE;
                   2232:                                                continue;
                   2233:                                        }
                   2234:                                        /*someone else is playing with the */
                   2235:                                        /* page.  We will have to wait.    */
                   2236:                                        PAGE_ASSERT_WAIT(
                   2237:                                                dst_page, THREAD_UNINT);
                   2238:                                        vm_object_unlock(object);
                   2239:                                        thread_block((void(*)(void))0);
                   2240:                                        vm_object_lock(object);
                   2241:                                        continue;
                   2242:                                }
                   2243:                                /* Someone else already cleaning the page? */
                   2244:                                if((dst_page->cleaning || dst_page->absent ||
                   2245:                                        dst_page->prep_pin_count != 0 ||
                   2246:                                        dst_page->wire_count != 0) && 
                   2247:                                        !dst_page->list_req_pending) {
                   2248:                                   if(user_page_list)
                   2249:                                           user_page_list[entry].phys_addr = 0;
                   2250:                                   entry++;
                   2251:                                   dst_offset += PAGE_SIZE;
                   2252:                                   xfer_size -= PAGE_SIZE;
                   2253:                                   continue;
                   2254:                                }
                   2255:                                VM_PAGE_GRAB_FICTITIOUS(alias_page);
                   2256:                                
                   2257:                                /* eliminate all mappings from the */
                   2258:                                /* original object and its prodigy */
                   2259:                                
                   2260:                                vm_page_lock_queues();
                   2261:                                pmap_page_protect(dst_page->phys_addr, 
                   2262:                                                                VM_PROT_NONE);
                   2263:                                /* Turn off busy indication on pending */
                   2264:                                /* pageout.  Note: we can only get here */
                   2265:                                /* in the request pending case.  */
                   2266:                                dst_page->list_req_pending = FALSE;
                   2267:                                dst_page->busy = FALSE;
                   2268:                                dst_page->cleaning = FALSE;
                   2269: 
                   2270:                                dirty = pmap_is_modified(dst_page->phys_addr);
                   2271:                                dirty = dirty ? TRUE : dst_page->dirty;
                   2272: 
                   2273:                                /* use pageclean setup, it is more convenient */
                   2274:                                /* even for the pageout cases here */
                   2275:                                vm_pageclean_setup(dst_page, alias_page,
                   2276:                                        upl->map_object, size - xfer_size);
                   2277:                                                
                   2278:                                if(!dirty) {
                   2279:                                        dst_page->dirty = FALSE;
                   2280:                                        dst_page->precious = TRUE;
                   2281:                                }
                   2282: 
                   2283:                                if(dst_page->pageout)
                   2284:                                        dst_page->busy = TRUE;
                   2285: 
                   2286:                                alias_page->absent = FALSE;
                   2287:                                if(!(cntrl_flags & UPL_CLEAN_IN_PLACE)) {
                   2288:                                        /* deny access to the target page */
                   2289:                                        /* while it is being worked on    */
                   2290:                                        if((!dst_page->pageout) &&
                   2291:                                                (dst_page->wire_count == 0)) {
                   2292:                                                dst_page->busy = TRUE;
                   2293:                                                dst_page->pageout = TRUE;
                   2294:                                                vm_page_wire(dst_page);
                   2295:                                        }
                   2296:                                }
                   2297:                                if(user_page_list) {
                   2298:                                        user_page_list[entry].phys_addr
                   2299:                                                = dst_page->phys_addr;
                   2300:                                        user_page_list[entry].dirty =   
                   2301:                                                        dst_page->dirty;
                   2302:                                        user_page_list[entry].pageout =
                   2303:                                                        dst_page->pageout;
                   2304:                                        user_page_list[entry].absent =
                   2305:                                                        dst_page->absent;
                   2306:                                }
                   2307: 
                   2308:                                vm_page_unlock_queues();
                   2309:                        }
                   2310:                        entry++;
                   2311:                        dst_offset += PAGE_SIZE;
                   2312:                        xfer_size -= PAGE_SIZE;
                   2313:                }
                   2314:        } else {
                   2315:                while (xfer_size) {
                   2316:                        dst_page = vm_page_lookup(object, dst_offset);
                   2317:                        if(dst_page != VM_PAGE_NULL) {
                   2318:                           if((dst_page->cleaning) && 
                   2319:                                        !(dst_page->list_req_pending)) {
                   2320:                                   /*someone else is writing to the */
                   2321:                                   /* page.  We will have to wait.  */
                   2322:                                   PAGE_ASSERT_WAIT(dst_page, THREAD_UNINT);
                   2323:                                   vm_object_unlock(object);
                   2324:                                   thread_block((void(*)(void))0);
                   2325:                                   vm_object_lock(object);
                   2326:                                   continue;
                   2327:                           }
                   2328:                           if ((dst_page->fictitious && 
                   2329:                                        dst_page->list_req_pending)) {
                   2330:                                /* dump the fictitious page */
                   2331:                                dst_page->list_req_pending = FALSE;
                   2332:                                dst_page->clustered = FALSE;
                   2333:                                vm_page_lock_queues();
                   2334:                                vm_page_free(dst_page);
                   2335:                                vm_page_unlock_queues();
                   2336:                           } else if ((dst_page->absent && 
                   2337:                                        dst_page->list_req_pending)) {
                   2338:                                /* the default_pager case */
                   2339:                                dst_page->list_req_pending = FALSE;
                   2340:                                dst_page->busy = FALSE;
                   2341:                                dst_page->clustered = FALSE;
                   2342:                           }
                   2343:                        }
                   2344:                        if((dst_page = vm_page_lookup(
                   2345:                                object, dst_offset)) == VM_PAGE_NULL) {
                   2346:                                /* need to allocate a page */
                   2347:                                dst_page = vm_page_alloc(object, dst_offset);
                   2348:                                if (dst_page == VM_PAGE_NULL) {
                   2349:                                   vm_object_unlock(object);
                   2350:                                   VM_PAGE_WAIT();
                   2351:                                   vm_object_lock(object);
                   2352:                                   continue;
                   2353:                                }
                   2354:                                dst_page->busy = FALSE;
                   2355:                                if(cntrl_flags & UPL_NO_SYNC) {
                   2356:                                        dst_page->page_lock = 0;
                   2357:                                        dst_page->unlock_request = 0;
                   2358:                                }
                   2359:                                dst_page->absent = TRUE;
                   2360:                                object->absent_count++;
                   2361:                        }
                   2362:                        dst_page->overwriting = TRUE;
                   2363:                        if(dst_page->fictitious) {
                   2364:                                panic("need corner case for fictitious page");
                   2365:                        }
                   2366:                        if(dst_page->page_lock) {
                   2367:                                do_m_lock = TRUE;
                   2368:                        }
                   2369:                        if(upl_ptr) {
                   2370:                                vm_page_t       alias_page;
                   2371: 
                   2372:                                VM_PAGE_GRAB_FICTITIOUS(alias_page);
                   2373:                                /* eliminate all mappings from the */
                   2374:                                /* original object and its prodigy */
                   2375:                                
                   2376:                                if(dst_page->busy) {
                   2377:                                        /*someone else is playing with the */
                   2378:                                        /* page.  We will have to wait.    */
                   2379:                                        PAGE_ASSERT_WAIT(
                   2380:                                                dst_page, THREAD_UNINT);
                   2381:                                        vm_object_unlock(object);
                   2382:                                        thread_block((void(*)(void))0);
                   2383:                                        vm_object_lock(object);
                   2384:                                        continue;
                   2385:                                }
                   2386:                                
                   2387:                                vm_page_lock_queues();
                   2388:                                pmap_page_protect(dst_page->phys_addr, 
                   2389:                                                                VM_PROT_NONE);
                   2390:                                dirty = pmap_is_modified(dst_page->phys_addr);
                   2391:                                dirty = dirty ? TRUE : dst_page->dirty;
                   2392: 
                   2393:                                vm_pageclean_setup(dst_page, alias_page,
                   2394:                                        upl->map_object, size - xfer_size);
                   2395: 
                   2396:                                if(cntrl_flags & UPL_CLEAN_IN_PLACE) {
                   2397:                                        /* clean in place for read implies   */
                   2398:                                        /* that a write will be done on all  */
                   2399:                                        /* the pages that are dirty before   */
                   2400:                                        /* a upl commit is done.  The caller */
                   2401:                                        /* is obligated to preserve the      */
                   2402:                                        /* contents of all pages marked      */
                   2403:                                        /* dirty. */
                   2404:                                        upl->flags |= UPL_CLEAR_DIRTY;
                   2405:                                }
                   2406: 
                   2407:                                if(!dirty) {
                   2408:                                        dst_page->dirty = FALSE;
                   2409:                                        dst_page->precious = TRUE;
                   2410:                                }
                   2411:                                                
                   2412:                                if (dst_page->wire_count == 0) {
                   2413:                                   /* deny access to the target page while */
                   2414:                                   /* it is being worked on */
                   2415:                                        dst_page->busy = TRUE;
                   2416:                                } else {
                   2417:                                        vm_page_wire(dst_page);
                   2418:                                }
                   2419:                                /* expect the page to be used */
                   2420:                                dst_page->reference = TRUE;
                   2421:                                dst_page->precious = 
                   2422:                                        (cntrl_flags & UPL_PRECIOUS) 
                   2423:                                                        ? TRUE : FALSE;
                   2424:                                alias_page->absent = FALSE;
                   2425:                                if(user_page_list) {
                   2426:                                        user_page_list[entry].phys_addr
                   2427:                                                = dst_page->phys_addr;
                   2428:                                        user_page_list[entry].dirty =
                   2429:                                                        dst_page->dirty;
                   2430:                                        user_page_list[entry].pageout =
                   2431:                                                        dst_page->pageout;
                   2432:                                        user_page_list[entry].absent =
                   2433:                                                        dst_page->absent;
                   2434:                                }
                   2435:                                vm_page_unlock_queues();
                   2436:                        }
                   2437:                        entry++;
                   2438:                        dst_offset += PAGE_SIZE;
                   2439:                        xfer_size -= PAGE_SIZE;
                   2440:                }
                   2441:        }
                   2442:        if(do_m_lock) {
                   2443:           vm_prot_t    access_required;
                   2444:           /* call back all associated pages from other users of the pager */
                   2445:           /* all future updates will be on data which is based on the     */
                   2446:           /* changes we are going to make here. Note: it is assumed that  */
                   2447:           /* we already hold copies of the data so we will not be seeing  */
                   2448:           /* an avalanche of incoming data from the pager */
                   2449:           access_required = (cntrl_flags & UPL_COPYOUT_FROM) 
                   2450:                                        ? VM_PROT_READ : VM_PROT_WRITE;
                   2451:           while (TRUE) {
                   2452:                kern_return_t   rc;
                   2453:                thread_t        thread;
                   2454: 
                   2455:                if(!object->pager_ready) {
                   2456:                   thread = current_thread();
                   2457:                   vm_object_assert_wait(object, 
                   2458:                                VM_OBJECT_EVENT_PAGER_READY, THREAD_UNINT);
                   2459:                   vm_object_unlock(object);
                   2460:                   thread_block((void (*)(void))0);
                   2461:                   if (thread->wait_result !=  THREAD_AWAKENED) {
                   2462:                      return(KERN_FAILURE);
                   2463:                   }
                   2464:                   vm_object_lock(object);
                   2465:                   continue;
                   2466:                }
                   2467: 
                   2468:                vm_object_unlock(object);
                   2469: 
                   2470:                if (rc = memory_object_data_unlock(
                   2471:                        object->pager,
                   2472:                        object->pager_request,
                   2473:                        dst_offset + object->paging_offset,
                   2474:                        size,
                   2475:                        access_required)) {
                   2476:                        if (rc == MACH_SEND_INTERRUPTED) 
                   2477:                                continue;
                   2478:                        else
                   2479:                                return KERN_FAILURE;
                   2480:                }
                   2481:                break;
                   2482:                
                   2483:           }
                   2484:           /* lets wait on the last page requested */
                   2485:           /* NOTE: we will have to update lock completed routine to signal */
                   2486:           if(dst_page != VM_PAGE_NULL && 
                   2487:                (access_required & dst_page->page_lock) != access_required) {
                   2488:                PAGE_ASSERT_WAIT(dst_page, THREAD_UNINT);
                   2489:                thread_block((void (*)(void))0);
                   2490:                vm_object_lock(object);
                   2491:           }
                   2492:        }
                   2493:        vm_object_unlock(object);
                   2494:        return KERN_SUCCESS;
                   2495: }
                   2496: 
                   2497: kern_return_t
                   2498: upl_system_list_request(
                   2499:        vm_object_t             object,
                   2500:        vm_object_offset_t      offset,
                   2501:        vm_size_t               size,
                   2502:        vm_size_t               super_cluster,
                   2503:        upl_t                   *upl,
                   2504:        upl_page_info_t         **user_page_list_ptr,
                   2505:        int                     page_list_count,
                   2506:        int                     cntrl_flags)
                   2507: {
                   2508:        if(object->paging_offset > offset)
                   2509:                return KERN_FAILURE;
                   2510:        offset = offset - object->paging_offset;
                   2511: 
                   2512: /* turns off super cluster exercised by the default_pager */
                   2513: /*
                   2514: super_cluster = size;
                   2515: */
                   2516:        if ((super_cluster > size) && 
                   2517:                        (vm_page_free_count > vm_page_free_reserved)) {
                   2518: 
                   2519:                vm_offset_t     base_offset;
                   2520:                vm_size_t       super_size;
                   2521: 
                   2522:                base_offset = (vm_offset_t)(offset &  
                   2523:                        ~((vm_offset_t) super_cluster - 1));
                   2524:                super_size = (offset+size) > (base_offset + super_cluster) ?
                   2525:                                super_cluster<<1 : super_cluster;
                   2526:                super_size = ((base_offset + super_size) > object->size) ? 
                   2527:                                (object->size - base_offset) : super_size;
                   2528:                if(offset > (base_offset + super_size))
                   2529:                   panic("upl_system_list_request: Missed target pageout 0x%x,0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", offset, base_offset, super_size, super_cluster, size, object->paging_offset);
                   2530:                /* apparently there is a case where the vm requests a */
                   2531:                /* page to be written out who's offset is beyond the  */
                   2532:                /* object size */
                   2533:                if((offset + size) > (base_offset + super_size))
                   2534:                   super_size = (offset + size) - base_offset;
                   2535: 
                   2536:                offset = base_offset;
                   2537:                size = super_size;
                   2538:        }
                   2539:        vm_fault_list_request(object, offset, size, upl, user_page_list_ptr,
                   2540:                                                page_list_count, cntrl_flags);
                   2541: }
                   2542: 
                   2543: 
                   2544: kern_return_t
                   2545: upl_map(
                   2546:        vm_map_t        map, 
                   2547:        upl_t           upl, 
                   2548:        vm_offset_t     *dst_addr)
                   2549: {
                   2550:        vm_size_t       size;
                   2551:        vm_offset_t     offset;
                   2552:        vm_offset_t     addr;
                   2553:        vm_page_t       m;
                   2554:        kern_return_t   kr;
                   2555: 
                   2556:        /* check to see if already mapped */
                   2557:        if(UPL_PAGE_LIST_MAPPED & upl->flags)
                   2558:                return KERN_FAILURE;
                   2559: 
                   2560:        offset = 0;  /* Always map the entire object */
                   2561:        size = upl->size;
                   2562:        
                   2563:        vm_object_lock(upl->map_object);
                   2564:        upl->map_object->ref_count++;
                   2565:        vm_object_res_reference(upl->map_object);
                   2566:        vm_object_unlock(upl->map_object);
                   2567: 
                   2568:        *dst_addr = 0;
                   2569: 
                   2570: 
                   2571:        /* NEED A UPL_MAP ALIAS */
                   2572:        kr = vm_map_enter(map, dst_addr, size, (vm_offset_t) 0, TRUE,
                   2573:                upl->map_object, offset, FALSE,
                   2574:                VM_PROT_DEFAULT, VM_PROT_ALL, VM_INHERIT_DEFAULT);
                   2575: 
                   2576:        if (kr != KERN_SUCCESS)
                   2577:                return(kr);
                   2578: 
                   2579:        for(addr=*dst_addr; size > 0; size-=PAGE_SIZE,addr+=PAGE_SIZE) {
                   2580:                m = vm_page_lookup(upl->map_object, offset);
                   2581:                if(m) {
                   2582:                        PMAP_ENTER(map->pmap, addr, m, VM_PROT_ALL, TRUE);
                   2583:                }
                   2584:                offset+=PAGE_SIZE;
                   2585:        }
                   2586: 
                   2587:        upl->flags |= UPL_PAGE_LIST_MAPPED;
                   2588:        upl->kaddr = *dst_addr;
                   2589:        return KERN_SUCCESS;
                   2590: }
                   2591:        
                   2592: 
                   2593: kern_return_t
                   2594: upl_un_map(
                   2595:        vm_map_t        map, 
                   2596:        upl_t           upl)
                   2597: {
                   2598:        vm_size_t       size;
                   2599: 
                   2600:        if(upl->flags & UPL_PAGE_LIST_MAPPED) {
                   2601:                size = upl->size;
                   2602:                vm_deallocate(map, upl->kaddr, size);
                   2603:                upl->flags &= ~UPL_PAGE_LIST_MAPPED;
                   2604:                upl->kaddr = (vm_offset_t) 0;
                   2605:                return KERN_SUCCESS;
                   2606:        } else {
                   2607:                return KERN_FAILURE;
                   2608:        }
                   2609: }
                   2610: 
                   2611: kern_return_t
                   2612: upl_commit_range(
                   2613:        upl_t           upl, 
                   2614:        vm_offset_t     offset, 
                   2615:        vm_size_t       size,
                   2616:        boolean_t       free_on_empty,
                   2617:        upl_page_info_t *page_list) 
                   2618: {
                   2619:        vm_offset_t     xfer_size = size;
                   2620:        vm_object_t     shadow_object = upl->map_object->shadow;
                   2621:        vm_object_t     object = upl->map_object;
                   2622:        vm_offset_t     target_offset;
                   2623:        vm_offset_t     page_offset;
                   2624:        int             entry;
                   2625: 
                   2626:        if ((offset + size) > upl->size)
                   2627:                return KERN_FAILURE;
                   2628: 
                   2629:        vm_object_lock(shadow_object);
                   2630: 
                   2631:        entry = offset/PAGE_SIZE;
                   2632:        target_offset = offset;
                   2633:        while(xfer_size) {
                   2634:                vm_page_t       t,m;
                   2635:                upl_page_info_t *p;
                   2636: 
                   2637:                if((t = vm_page_lookup(object,
                   2638:                        (vm_offset_t)target_offset)) != NULL) {
                   2639: 
                   2640:                        t->pageout = FALSE;
                   2641:                        page_offset = (vm_offset_t)t->offset;
                   2642:                        VM_PAGE_FREE(t);
                   2643:                        t = VM_PAGE_NULL;
                   2644:                        m = vm_page_lookup(shadow_object, 
                   2645:                                        page_offset + object->shadow_offset);
                   2646:                        if(m != VM_PAGE_NULL) {
                   2647:                           vm_object_paging_end(shadow_object);
                   2648:                           vm_page_lock_queues();
                   2649:                           if (upl->flags & UPL_CLEAR_DIRTY) {
                   2650:                                pmap_clear_modify(m->phys_addr);
                   2651:                                m->dirty = FALSE;
                   2652:                           }
                   2653:                           if(page_list) {
                   2654:                                p = &(page_list[entry]);
                   2655:                                if(p->phys_addr && p->pageout && !m->pageout) {
                   2656:                                        m->busy = TRUE;
                   2657:                                        m->pageout = TRUE;
                   2658:                                        vm_page_wire(m);
                   2659:                                } else if (page_list[entry].phys_addr &&
                   2660:                                                !p->pageout && m->pageout) {
                   2661:                                        m->pageout = FALSE;
                   2662:                                        vm_page_unwire(m);
                   2663:                                        PAGE_WAKEUP_DONE(m);
                   2664:                                }
                   2665:                                page_list[entry].phys_addr = 0;
                   2666:                           }
                   2667:                           if(m->laundry) {
                   2668:                              vm_page_laundry_count--;
                   2669:                              m->laundry = FALSE;
                   2670:                              if (vm_page_laundry_count < vm_page_laundry_min) {
                   2671:                                 vm_page_laundry_min = 0;
                   2672:                                 thread_wakeup((event_t) 
                   2673:                                             &vm_page_laundry_count);
                   2674:                              }
                   2675:                           }
                   2676:                           if(m->pageout) {
                   2677:                              m->cleaning = FALSE;
                   2678:                              m->pageout = FALSE;
                   2679: #if MACH_CLUSTER_STATS
                   2680:                              if (m->wanted) vm_pageout_target_collisions++;
                   2681: #endif
                   2682:                              pmap_page_protect(m->phys_addr, VM_PROT_NONE);
                   2683:                              m->dirty = pmap_is_modified(m->phys_addr);
                   2684:                              if(m->dirty) {
                   2685:                                 CLUSTER_STAT(
                   2686:                                      vm_pageout_target_page_dirtied++;)
                   2687:                                  vm_page_unwire(m);/* reactivates */
                   2688:                                  VM_STAT(reactivations++);
                   2689:                                  PAGE_WAKEUP_DONE(m);
                   2690:                                      } else if (m->prep_pin_count != 0) {
                   2691:                                  vm_page_pin_lock();
                   2692:                                  if (m->pin_count != 0) {
                   2693:                                     /* page is pinned; reactivate */
                   2694:                                     CLUSTER_STAT(
                   2695:                                                vm_pageout_target_page_pinned++;)
                   2696:                                     vm_page_unwire(m);/* reactivates */
                   2697:                                     VM_STAT(reactivations++);
                   2698:                                     PAGE_WAKEUP_DONE(m);
                   2699:                                  } else {
                   2700:                                    /*
                   2701:                                     * page is prepped but not pinned; 
                   2702:                                    * send it into limbo.  Note that
                   2703:                                     * vm_page_free (which will be 
                   2704:                                    * called after releasing the pin 
                   2705:                                    * lock) knows how to handle a page 
                   2706:                                    * with limbo set.
                   2707:                                     */
                   2708:                                     m->limbo = TRUE;
                   2709:                                     CLUSTER_STAT(
                   2710:                                                 vm_pageout_target_page_limbo++;)
                   2711:                                  }
                   2712:                                  vm_page_pin_unlock();
                   2713:                                  if (m->limbo)
                   2714:                                     vm_page_free(m);
                   2715:                                 } else {
                   2716:                                     CLUSTER_STAT(
                   2717:                                               vm_pageout_target_page_freed++;)
                   2718:                                     vm_page_free(m);/* clears busy, etc. */
                   2719:                                 }
                   2720:                                 vm_page_unlock_queues();
                   2721:                                 target_offset += PAGE_SIZE;
                   2722:                                 xfer_size -= PAGE_SIZE;
                   2723:                                 entry++;
                   2724:                                  continue;
                   2725:                              }
                   2726:                              if (!m->active && !m->inactive) {
                   2727:                                    if (m->reference || m->prep_pin_count != 0)
                   2728:                                       vm_page_activate(m);
                   2729:                                    else
                   2730:                                       vm_page_deactivate(m);
                   2731:                               }
                   2732: #if MACH_CLUSTER_STATS
                   2733:                               m->dirty = pmap_is_modified(m->phys_addr);
                   2734: 
                   2735:                               if (m->dirty)   vm_pageout_cluster_dirtied++;
                   2736:                               else            vm_pageout_cluster_cleaned++;
                   2737:                               if (m->wanted)  vm_pageout_cluster_collisions++;
                   2738: #else
                   2739:                               m->dirty = 0;
                   2740: #endif
                   2741: 
                   2742:                               if((m->busy) && (m->cleaning)) {
                   2743:                                  /* the request_page_list case */
                   2744:                                if(m->absent) {
                   2745:                                   m->absent = FALSE;
                   2746:                                   if(shadow_object->absent_count == 1)
                   2747:                                      vm_object_absent_release(shadow_object);
                   2748:                                   else
                   2749:                                      shadow_object->absent_count--;
                   2750:                                }
                   2751:                                 m->overwriting = FALSE;
                   2752:                                  m->busy = FALSE;
                   2753:                                  m->dirty = FALSE;
                   2754:                               }
                   2755:                              else if (m->overwriting) {
                   2756:                                 /* alternate request page list, write to 
                   2757:                                 /* page_list case.  Occurs when the original
                   2758:                                 /* page was wired at the time of the list
                   2759:                                 /* request */
                   2760:                                 assert(m->wire_count != 0);
                   2761:                                 vm_page_unwire(m);/* reactivates */
                   2762:                                 m->overwriting = FALSE;
                   2763:                              }
                   2764:                               m->cleaning = FALSE;
                   2765:                               /*
                   2766:                                * Wakeup any thread waiting for the page to be un-cleaning.
                   2767:                                */
                   2768:                               PAGE_WAKEUP(m);
                   2769:                               vm_page_unlock_queues();
                   2770: 
                   2771:                           }
                   2772:                }
                   2773:                target_offset += PAGE_SIZE;
                   2774:                xfer_size -= PAGE_SIZE;
                   2775:                entry++;
                   2776:        }
                   2777: 
                   2778:        vm_object_unlock(shadow_object);
                   2779:        if(free_on_empty) {
                   2780:                if(queue_empty(&upl->map_object->memq)) {
                   2781:                        upl_destroy(upl);
                   2782:                }
                   2783:        }
                   2784:        return KERN_SUCCESS;
                   2785: }
                   2786: 
                   2787: upl_abort_range(
                   2788:        upl_t           upl, 
                   2789:        vm_offset_t     offset, 
                   2790:        vm_size_t       size,
                   2791:        int             error) 
                   2792: {
                   2793:        vm_offset_t     xfer_size = size;
                   2794:        vm_object_t     shadow_object = upl->map_object->shadow;
                   2795:        vm_object_t     object = upl->map_object;
                   2796:        vm_offset_t     target_offset;
                   2797:        vm_offset_t     page_offset;
                   2798:        int             entry;
                   2799: 
                   2800:        if ((offset + size) > upl->size)
                   2801:                return KERN_FAILURE;
                   2802: 
                   2803:        vm_object_lock(shadow_object);
                   2804: 
                   2805:        entry = offset/PAGE_SIZE;
                   2806:        target_offset = offset;
                   2807:        while(xfer_size) {
                   2808:                vm_page_t       t,m;
                   2809:                upl_page_info_t *p;
                   2810: 
                   2811:                if((t = vm_page_lookup(object,
                   2812:                        (vm_offset_t)target_offset)) != NULL) {
                   2813: 
                   2814:                        t->pageout = FALSE;
                   2815:                        page_offset = (vm_offset_t)t->offset;
                   2816:                        VM_PAGE_FREE(t);
                   2817:                        t = VM_PAGE_NULL;
                   2818:                        m = vm_page_lookup(shadow_object, 
                   2819:                                        page_offset + object->shadow_offset);
                   2820:                   if(m != VM_PAGE_NULL) {
                   2821:                        vm_object_paging_end(m->object);
                   2822:                        vm_page_lock_queues();
                   2823:                        if(m->absent) {
                   2824:                                /* COPYOUT = FALSE case */
                   2825:                                /* check for error conditions which must */
                   2826:                                /* be passed back to the pages customer  */
                   2827:                                if(error & UPL_ABORT_RESTART) {
                   2828:                                        m->restart = TRUE;
                   2829:                                        m->absent = FALSE;
                   2830:                                        vm_object_absent_release(m->object);
                   2831:                                        m->page_error = KERN_MEMORY_ERROR;
                   2832:                                        m->error = TRUE;
                   2833:                                } else if(error & UPL_ABORT_UNAVAILABLE) {
                   2834:                                        m->restart = FALSE;
                   2835:                                        m->unusual = TRUE;
                   2836:                                        m->clustered = FALSE;
                   2837:                                } else if(error & UPL_ABORT_ERROR) {
                   2838:                                        m->restart = FALSE;
                   2839:                                        m->absent = FALSE;
                   2840:                                        vm_object_absent_release(m->object);
                   2841:                                        m->page_error = KERN_MEMORY_ERROR;
                   2842:                                        m->error = TRUE;
                   2843:                                } else {
                   2844:                                        m->clustered = TRUE;
                   2845:                                }
                   2846:                                
                   2847: 
                   2848:                                m->cleaning = FALSE;
                   2849:                                m->overwriting = FALSE;
                   2850:                                PAGE_WAKEUP_DONE(m);
                   2851:                                if(m->clustered) {
                   2852:                                        vm_page_free(m);
                   2853:                                } else {
                   2854:                                        vm_page_activate(m);
                   2855:                                }
                   2856: 
                   2857:                                vm_page_unlock_queues();
                   2858:                                target_offset += PAGE_SIZE;
                   2859:                                xfer_size -= PAGE_SIZE;
                   2860:                                entry++;
                   2861:                                continue;
                   2862:                        }
                   2863:                        /*                          
                   2864:                         * Handle the trusted pager throttle.
                   2865:                         */                     
                   2866:                        if (m->laundry) { 
                   2867:                                vm_page_laundry_count--;
                   2868:                                m->laundry = FALSE;  
                   2869:                                if (vm_page_laundry_count 
                   2870:                                                < vm_page_laundry_min) {
                   2871:                                        vm_page_laundry_min = 0;
                   2872:                                        thread_wakeup((event_t) 
                   2873:                                                &vm_page_laundry_count); 
                   2874:                                }                    
                   2875:                        }         
                   2876:                        if(m->pageout) {
                   2877:                                assert(m->busy);
                   2878:                                assert(m->wire_count == 1);
                   2879:                                m->pageout = FALSE;
                   2880:                                vm_page_unwire(m);
                   2881:                        }
                   2882:                        m->dirty = TRUE;
                   2883:                        m->cleaning = FALSE;
                   2884:                        m->busy = FALSE;
                   2885:                        m->overwriting = FALSE;
                   2886:                        PAGE_WAKEUP(m);
                   2887:                        vm_page_unlock_queues();
                   2888:                }
                   2889:           }
                   2890:           target_offset += PAGE_SIZE;
                   2891:           xfer_size -= PAGE_SIZE;
                   2892:           entry++;
                   2893:        }
                   2894:        vm_object_unlock(shadow_object);
                   2895:        if(error & UPL_ABORT_FREE_ON_EMPTY) {
                   2896:                if(queue_empty(&upl->map_object->memq)) {
                   2897:                        upl_destroy(upl);
                   2898:                }
                   2899:        }
                   2900:        return KERN_SUCCESS;
                   2901: }
                   2902: 
                   2903: kern_return_t
                   2904: upl_abort(
                   2905:        upl_t   upl,
                   2906:        int     error)
                   2907: {
                   2908:        vm_object_t             object = NULL;
                   2909:        vm_object_t             shadow_object = NULL;
                   2910:        vm_offset_t             offset;
                   2911:        vm_object_offset_t      shadow_offset;
                   2912:        vm_object_offset_t      target_offset;
                   2913:        int                     i;
                   2914:        vm_page_t               t,m;
                   2915: 
                   2916:        object = upl->map_object;
                   2917: 
                   2918:        if(object == NULL) {
                   2919:                panic("upl_abort: upl object is not backed by an object");
                   2920:                return KERN_INVALID_ARGUMENT;
                   2921:        }
                   2922: 
                   2923:        shadow_object = upl->map_object->shadow;
                   2924:        shadow_offset = upl->map_object->shadow_offset;
                   2925:        offset = 0;
                   2926:        vm_object_lock(shadow_object);
                   2927:        for(i = 0; i<(upl->size); i+=PAGE_SIZE) {
                   2928:            if((t = vm_page_lookup(object,
                   2929:                        (vm_offset_t)offset)) != NULL) {
                   2930:                target_offset = t->offset + shadow_offset;
                   2931:                if((m = vm_page_lookup(shadow_object, target_offset)) != NULL) {
                   2932:                        vm_object_paging_end(m->object);
                   2933:                        vm_page_lock_queues();
                   2934:                        if(m->absent) {
                   2935:                                /* COPYOUT = FALSE case */
                   2936:                                /* check for error conditions which must */
                   2937:                                /* be passed back to the pages customer  */
                   2938:                                if(error & UPL_ABORT_RESTART) {
                   2939:                                        m->restart = TRUE;
                   2940:                                        m->absent = FALSE;
                   2941:                                        vm_object_absent_release(m->object);
                   2942:                                        m->page_error = KERN_MEMORY_ERROR;
                   2943:                                        m->error = TRUE;
                   2944:                                } else if(error & UPL_ABORT_UNAVAILABLE) {
                   2945:                                        m->restart = FALSE;
                   2946:                                        m->unusual = TRUE;
                   2947:                                        m->clustered = FALSE;
                   2948:                                } else if(error & UPL_ABORT_ERROR) {
                   2949:                                        m->restart = FALSE;
                   2950:                                        m->absent = FALSE;
                   2951:                                        vm_object_absent_release(m->object);
                   2952:                                        m->page_error = KERN_MEMORY_ERROR;
                   2953:                                        m->error = TRUE;
                   2954:                                } else {
                   2955:                                        m->clustered = TRUE;
                   2956:                                }
                   2957:                                
                   2958: 
                   2959:                                m->cleaning = FALSE;
                   2960:                                m->overwriting = FALSE;
                   2961:                                PAGE_WAKEUP_DONE(m);
                   2962:                                if(m->clustered) {
                   2963:                                        vm_page_free(m);
                   2964:                                } else {
                   2965:                                        vm_page_activate(m);
                   2966:                                }
                   2967: 
                   2968:                                vm_page_unlock_queues();
                   2969:                                continue;
                   2970:                        }
                   2971:                        /*                          
                   2972:                         * Handle the trusted pager throttle.
                   2973:                         */                     
                   2974:                        if (m->laundry) { 
                   2975:                                vm_page_laundry_count--;
                   2976:                                m->laundry = FALSE;  
                   2977:                                if (vm_page_laundry_count 
                   2978:                                                < vm_page_laundry_min) {
                   2979:                                        vm_page_laundry_min = 0;
                   2980:                                        thread_wakeup((event_t) 
                   2981:                                                &vm_page_laundry_count); 
                   2982:                                }                    
                   2983:                        }         
                   2984:                        if(m->pageout) {
                   2985:                                assert(m->busy);
                   2986:                                assert(m->wire_count == 1);
                   2987:                                m->pageout = FALSE;
                   2988:                                vm_page_unwire(m);
                   2989:                        }
                   2990:                        m->dirty = TRUE;
                   2991:                        m->cleaning = FALSE;
                   2992:                        m->busy = FALSE;
                   2993:                        m->overwriting = FALSE;
                   2994:                        PAGE_WAKEUP(m);
                   2995:                        vm_page_unlock_queues();
                   2996:                }
                   2997:           }
                   2998:           offset += PAGE_SIZE;
                   2999:        }
                   3000:        vm_object_unlock(shadow_object);
                   3001:        /* Remove all the pages from the map object so */
                   3002:        /* vm_pageout_object_terminate will work properly. */
                   3003:        while (!queue_empty(&upl->map_object->memq)) {
                   3004:                vm_page_t p;
                   3005: 
                   3006:                p = (vm_page_t) queue_first(&upl->map_object->memq);
                   3007: 
                   3008:                assert(p->private);
                   3009:                assert(p->pageout);
                   3010:                p->pageout = FALSE;
                   3011:                assert(!p->cleaning);
                   3012: 
                   3013:                VM_PAGE_FREE(p);
                   3014:        }
                   3015:        upl_destroy(upl);
                   3016:        return KERN_SUCCESS;
                   3017: }
                   3018: 
                   3019: /* an option on commit should be wire */
                   3020: kern_return_t
                   3021: upl_commit(
                   3022:        upl_t           upl,
                   3023:        upl_page_info_t *page_list)
                   3024: {
                   3025:        if (upl->flags & UPL_CLEAR_DIRTY) {
                   3026:                vm_object_t     shadow_object = upl->map_object->shadow;
                   3027:                vm_object_t     object = upl->map_object;
                   3028:                vm_object_offset_t target_offset;
                   3029:                vm_size_t       xfer_end;
                   3030: 
                   3031:                vm_page_t       t,m;
                   3032: 
                   3033:                vm_object_lock(shadow_object);
                   3034: 
                   3035:                target_offset = object->shadow_offset;
                   3036:                xfer_end = upl->size + object->shadow_offset;
                   3037: 
                   3038:                while(target_offset <= xfer_end) {
                   3039:                        if ((t = vm_page_lookup(object, 
                   3040:                                target_offset - object->shadow_offset))
                   3041:                                != NULL) {
                   3042:                                m = vm_page_lookup(
                   3043:                                        shadow_object, target_offset);
                   3044:                                if(m != VM_PAGE_NULL) {
                   3045:                                        pmap_clear_modify(m->phys_addr);
                   3046:                                        m->dirty = FALSE;
                   3047:                                }
                   3048:                        }
                   3049:                        target_offset += PAGE_SIZE;
                   3050:                }
                   3051:                vm_object_unlock(shadow_object);
                   3052:        }
                   3053:        if (page_list) {
                   3054:                vm_object_t     shadow_object = upl->map_object->shadow;
                   3055:                vm_object_t     object = upl->map_object;
                   3056:                vm_object_offset_t target_offset;
                   3057:                vm_size_t       xfer_end;
                   3058:                int             entry;
                   3059: 
                   3060:                vm_page_t       m;
                   3061:                upl_page_info_t *p;
                   3062: 
                   3063:                vm_object_lock(shadow_object);
                   3064: 
                   3065:                entry = 0;
                   3066:                target_offset = object->shadow_offset;
                   3067:                xfer_end = upl->size + object->shadow_offset;
                   3068: 
                   3069:                while(target_offset <= xfer_end) {
                   3070: 
                   3071:                        m = vm_page_lookup(shadow_object, target_offset);
                   3072:                        if(m != VM_PAGE_NULL) {
                   3073:                           p = &(page_list[entry]);
                   3074:                           if(page_list[entry].phys_addr &&
                   3075:                                                p->pageout && !m->pageout) {
                   3076:                                        vm_page_lock_queues();
                   3077:                                        m->busy = TRUE;
                   3078:                                        m->pageout = TRUE;
                   3079:                                        vm_page_wire(m);
                   3080:                                        vm_page_unlock_queues();
                   3081:                           } else if (page_list[entry].phys_addr &&
                   3082:                                                !p->pageout && m->pageout) {
                   3083:                                        vm_page_lock_queues();
                   3084:                                        m->pageout = FALSE;
                   3085:                                        vm_page_unwire(m);
                   3086:                                        PAGE_WAKEUP_DONE(m);
                   3087:                                        vm_page_unlock_queues();
                   3088:                           }
                   3089:                           page_list[entry].phys_addr = 0;
                   3090:                        }
                   3091:                        target_offset += PAGE_SIZE;
                   3092:                        entry++;
                   3093:                }
                   3094: 
                   3095:                vm_object_unlock(shadow_object);
                   3096:        }
                   3097:        upl_destroy(upl);
                   3098:        return KERN_SUCCESS;
                   3099: }
                   3100: 
                   3101: upl_t
                   3102: upl_create(
                   3103:        boolean_t       internal)
                   3104: {
                   3105:        upl_t   upl;
                   3106: 
                   3107:        if(internal) {
                   3108:                upl = (upl_t)kalloc(sizeof(struct upl)
                   3109:                                + (sizeof(struct upl_page_info)*20));
                   3110:        } else {
                   3111:                upl = (upl_t)kalloc(sizeof(struct upl));
                   3112:        }
                   3113:        upl->flags = 0;
                   3114:        upl->src_object = NULL;
                   3115:        upl->kaddr = (vm_offset_t)0;
                   3116:        upl->size = 0;
                   3117:        upl->map_object = NULL;
                   3118:        upl->ref_count = 1;
                   3119:        upl_lock_init(upl);
                   3120:        return(upl);
                   3121: }
                   3122: 
                   3123: void
                   3124: upl_destroy(
                   3125:        upl_t   upl)
                   3126: {
                   3127:        vm_object_deallocate(upl->map_object);
                   3128:        if(upl->flags & UPL_INTERNAL) {
                   3129:                kfree((vm_offset_t)upl,
                   3130:                        sizeof(struct upl) + (sizeof(struct upl_page_info)*20));
                   3131:        } else {
                   3132:                kfree((vm_offset_t)upl, sizeof(struct upl));
                   3133:        }
                   3134: }
                   3135: 
                   3136: vm_size_t
                   3137: upl_get_internal_pagelist_offset()
                   3138: {
                   3139:        return sizeof(struct upl);
                   3140: }
                   3141: 
                   3142: void
                   3143: upl_set_dirty(
                   3144:        upl_t   upl)
                   3145: {
                   3146:        upl->flags |= UPL_CLEAR_DIRTY;
                   3147: }
                   3148: 
                   3149: void
                   3150: upl_clear_dirty(
                   3151:        upl_t   upl)
                   3152: {
                   3153:        upl->flags &= ~UPL_CLEAR_DIRTY;
                   3154: }
                   3155: 
                   3156: 
                   3157: 
                   3158: 
                   3159: #if    MACH_KDB
                   3160: #include <ddb/db_output.h>
                   3161: #include <ddb/db_print.h>
                   3162: #include <vm/vm_print.h>
                   3163: 
                   3164: #define        printf  kdbprintf
                   3165: extern int     db_indent;
                   3166: void           db_pageout(void);
                   3167: 
                   3168: void
                   3169: db_vm(void)
                   3170: {
                   3171:        extern int vm_page_gobble_count;
                   3172:        extern int vm_page_limbo_count, vm_page_limbo_real_count;
                   3173:        extern int vm_page_pin_count;
                   3174: 
                   3175:        iprintf("VM Statistics:\n");
                   3176:        db_indent += 2;
                   3177:        iprintf("pages:\n");
                   3178:        db_indent += 2;
                   3179:        iprintf("activ %5d  inact %5d  free  %5d",
                   3180:                vm_page_active_count, vm_page_inactive_count,
                   3181:                vm_page_free_count);
                   3182:        printf("   wire  %5d  gobbl %5d\n",
                   3183:               vm_page_wire_count, vm_page_gobble_count);
                   3184:        iprintf("laund %5d  limbo %5d  lim_r %5d   pin   %5d\n",
                   3185:                vm_page_laundry_count, vm_page_limbo_count,
                   3186:                vm_page_limbo_real_count, vm_page_pin_count);
                   3187:        db_indent -= 2;
                   3188:        iprintf("target:\n");
                   3189:        db_indent += 2;
                   3190:        iprintf("min   %5d  inact %5d  free  %5d",
                   3191:                vm_page_free_min, vm_page_inactive_target,
                   3192:                vm_page_free_target);
                   3193:        printf("   resrv %5d\n", vm_page_free_reserved);
                   3194:        db_indent -= 2;
                   3195: 
                   3196:        iprintf("burst:\n");
                   3197:        db_indent += 2;
                   3198:        iprintf("max   %5d  min   %5d  wait  %5d   empty %5d\n",
                   3199:                  vm_pageout_burst_max, vm_pageout_burst_min,
                   3200:                  vm_pageout_burst_wait, vm_pageout_empty_wait);
                   3201:        db_indent -= 2;
                   3202:        iprintf("pause:\n");
                   3203:        db_indent += 2;
                   3204:        iprintf("count %5d  max   %5d\n",
                   3205:                vm_pageout_pause_count, vm_pageout_pause_max);
                   3206: #if    MACH_COUNTERS
                   3207:        iprintf("scan_continue called %8d\n", c_vm_pageout_scan_continue);
                   3208: #endif /* MACH_COUNTERS */
                   3209:        db_indent -= 2;
                   3210:        db_pageout();
                   3211:        db_indent -= 2;
                   3212: }
                   3213: 
                   3214: void
                   3215: db_pageout(void)
                   3216: {
                   3217:        extern int c_limbo_page_free;
                   3218:        extern int c_limbo_convert;
                   3219: #if    MACH_COUNTERS
                   3220:        extern int c_laundry_pages_freed;
                   3221: #endif /* MACH_COUNTERS */
                   3222: 
                   3223:        iprintf("Pageout Statistics:\n");
                   3224:        db_indent += 2;
                   3225:        iprintf("active %5d  inactv %5d\n",
                   3226:                vm_pageout_active, vm_pageout_inactive);
                   3227:        iprintf("nolock %5d  avoid  %5d  busy   %5d  absent %5d\n",
                   3228:                vm_pageout_inactive_nolock, vm_pageout_inactive_avoid,
                   3229:                vm_pageout_inactive_busy, vm_pageout_inactive_absent);
                   3230:        iprintf("used   %5d  clean  %5d  dirty  %5d\n",
                   3231:                vm_pageout_inactive_used, vm_pageout_inactive_clean,
                   3232:                vm_pageout_inactive_dirty);
                   3233:        iprintf("pinned %5d  limbo  %5d  setup_limbo %5d  setup_unprep %5d\n",
                   3234:                vm_pageout_inactive_pinned, vm_pageout_inactive_limbo,
                   3235:                vm_pageout_setup_limbo, vm_pageout_setup_unprepped);
                   3236:        iprintf("limbo_page_free  %5d   limbo_convert  %5d\n",
                   3237:                c_limbo_page_free, c_limbo_convert);
                   3238: #if    MACH_COUNTERS
                   3239:        iprintf("laundry_pages_freed %d\n", c_laundry_pages_freed);
                   3240: #endif /* MACH_COUNTERS */
                   3241: #if    MACH_CLUSTER_STATS
                   3242:        iprintf("Cluster Statistics:\n");
                   3243:        db_indent += 2;
                   3244:        iprintf("dirtied   %5d   cleaned  %5d   collisions  %5d\n",
                   3245:                vm_pageout_cluster_dirtied, vm_pageout_cluster_cleaned,
                   3246:                vm_pageout_cluster_collisions);
                   3247:        iprintf("clusters  %5d   conversions  %5d\n",
                   3248:                vm_pageout_cluster_clusters, vm_pageout_cluster_conversions);
                   3249:        db_indent -= 2;
                   3250:        iprintf("Target Statistics:\n");
                   3251:        db_indent += 2;
                   3252:        iprintf("collisions   %5d   page_dirtied  %5d   page_freed  %5d\n",
                   3253:                vm_pageout_target_collisions, vm_pageout_target_page_dirtied,
                   3254:                vm_pageout_target_page_freed);
                   3255:        iprintf("page_pinned  %5d   page_limbo    %5d\n",
                   3256:                vm_pageout_target_page_pinned, vm_pageout_target_page_limbo);
                   3257:        db_indent -= 2;
                   3258: #endif /* MACH_CLUSTER_STATS */
                   3259:        db_indent -= 2;
                   3260: }
                   3261: 
                   3262: #if MACH_CLUSTER_STATS
                   3263: unsigned long vm_pageout_cluster_dirtied = 0;
                   3264: unsigned long vm_pageout_cluster_cleaned = 0;
                   3265: unsigned long vm_pageout_cluster_collisions = 0;
                   3266: unsigned long vm_pageout_cluster_clusters = 0;
                   3267: unsigned long vm_pageout_cluster_conversions = 0;
                   3268: unsigned long vm_pageout_target_collisions = 0;
                   3269: unsigned long vm_pageout_target_page_dirtied = 0;
                   3270: unsigned long vm_pageout_target_page_freed = 0;
                   3271: unsigned long vm_pageout_target_page_pinned = 0;
                   3272: unsigned long vm_pageout_target_page_limbo = 0;
                   3273: #define CLUSTER_STAT(clause)   clause
                   3274: #else  /* MACH_CLUSTER_STATS */
                   3275: #define CLUSTER_STAT(clause)
                   3276: #endif /* MACH_CLUSTER_STATS */
                   3277: 
                   3278: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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