Annotation of XNU/osfmk/vm/memory_object.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/memory_object.c
                     54:  *     Author: Michael Wayne Young
                     55:  *
                     56:  *     External memory management interface control functions.
                     57:  */
                     58: 
                     59: #ifdef MACH_BSD
                     60: /* THIS code should be removed when the component merge is completed */
                     61: extern int vnode_pager_workaround;
                     62: #endif
                     63: 
                     64: #include <advisory_pageout.h>
                     65: 
                     66: /*
                     67:  *     Interface dependencies:
                     68:  */
                     69: 
                     70: #include <mach/std_types.h>    /* For pointer_t */
                     71: #include <mach/mach_types.h>
                     72: 
                     73: #include <mach/kern_return.h>
                     74: #include <mach/memory_object.h>
                     75: #include <mach/memory_object_default.h>
                     76: #include <mach/memory_object_control_server.h>
                     77: #include <mach/mach_host_server.h>
                     78: #include <mach/boolean.h>
                     79: #include <mach/vm_prot.h>
                     80: #include <mach/message.h>
                     81: 
                     82: #include <vm/vm_object.h>
                     83: #include <vm/vm_fault.h>
                     84: /*
                     85:  *     Implementation dependencies:
                     86:  */
                     87: #include <string.h>            /* For memcpy() */
                     88: 
                     89: #include <vm/memory_object.h>
                     90: #include <vm/vm_page.h>
                     91: #include <vm/vm_pageout.h>
                     92: #include <vm/pmap.h>           /* For pmap_clear_modify */
                     93: #include <kern/xpr.h>          
                     94: #include <kern/thread.h>       /* For current_thread() */
                     95: #include <kern/host.h>
                     96: #include <vm/vm_kern.h>                /* For kernel_map, vm_move */
                     97: #include <vm/vm_map.h>         /* For vm_map_pageable */
                     98: #include <ipc/ipc_port.h>
                     99: #include <ipc/ipc_space.h>
                    100: 
                    101: 
                    102: 
                    103: #include <kern/misc_protos.h>
                    104: 
                    105: #if    MACH_PAGEMAP
                    106: #include <vm/vm_external.h>
                    107: #endif /* MACH_PAGEMAP */
                    108: 
                    109: ipc_port_t     memory_manager_default = IP_NULL;
                    110: vm_size_t      memory_manager_default_cluster = 0;
                    111: decl_mutex_data(,memory_manager_default_lock)
                    112: 
                    113: /*
                    114:  *     Forward ref to file-local function:
                    115:  */
                    116: boolean_t
                    117: memory_object_update(vm_object_t,
                    118:        vm_offset_t, vm_size_t, memory_object_return_t, boolean_t, vm_prot_t);
                    119: 
                    120: /*
                    121:  *     Important note:
                    122:  *             All of the external (user interface) routines gain a reference
                    123:  *             to the object (first argument) as part of the automatic
                    124:  *             argument conversion. Explicit deallocation is necessary.
                    125:  */
                    126: 
                    127: kern_return_t
                    128: memory_object_data_supply(
                    129:        register
                    130:         vm_object_t            object,
                    131:        register
                    132:        vm_offset_t             offset,
                    133:        vm_offset_t             data,
                    134:        mach_msg_type_number_t  data_cnt,
                    135:        vm_prot_t               lock_value,
                    136:        boolean_t               precious,
                    137:        ipc_port_t              reply_to,
                    138:        mach_msg_type_name_t    reply_to_type)
                    139: {
                    140:        vm_map_copy_t   data_copy = (vm_map_copy_t)data;
                    141:        kern_return_t   result = KERN_SUCCESS;
                    142:        vm_offset_t     error_offset = 0;
                    143:        register
                    144:        vm_page_t       m;
                    145:        register
                    146:        vm_page_t       data_m;
                    147:        vm_size_t       original_length;
                    148:        vm_offset_t     original_offset;
                    149:        vm_page_t       *page_list;
                    150:        boolean_t       was_absent;
                    151:        vm_map_copy_t   orig_copy = data_copy;
                    152:        boolean_t       was_clustered;
                    153: 
                    154: 
                    155:         XPR(XPR_MEMORY_OBJECT,
                    156:             "m_o_data_supply, object 0x%X, offset 0x%X data_cnt 0x%X\n",
                    157:             (integer_t)object, offset, data_cnt, 0, 0);
                    158: 
                    159:        /*
                    160:         *      Look for bogus arguments
                    161:         */
                    162: 
                    163:        if (object == VM_OBJECT_NULL) {
                    164:                return(KERN_INVALID_ARGUMENT);
                    165:        }
                    166: 
                    167:        if (lock_value & ~VM_PROT_ALL) {
                    168:                vm_object_deallocate(object);
                    169:                return(KERN_INVALID_ARGUMENT);
                    170:        }
                    171: 
                    172:        if (! page_aligned(data_cnt)) {
                    173:            vm_object_deallocate(object);
                    174:            return(KERN_INVALID_ARGUMENT);
                    175:        }
                    176: 
                    177:        /*
                    178:         *      Adjust the offset from the memory object to the offset
                    179:         *      within the vm_object.
                    180:         */
                    181: 
                    182:        original_length = data_cnt;
                    183:        original_offset = offset;
                    184: 
                    185:        assert(data_copy->type == VM_MAP_COPY_PAGE_LIST);
                    186:        page_list = &data_copy->cpy_page_list[0];
                    187: 
                    188:        vm_object_lock(object);
                    189:        vm_object_paging_begin(object);
                    190:        offset -= object->paging_offset;
                    191: 
                    192:        /*
                    193:         *      Loop over copy stealing pages for pagein.
                    194:         */
                    195: 
                    196:        for (; data_cnt > 0 ; data_cnt -= PAGE_SIZE, offset += PAGE_SIZE) {
                    197: 
                    198:                assert(data_copy != VM_MAP_COPY_NULL);
                    199:                assert(data_copy->type == VM_MAP_COPY_PAGE_LIST);
                    200:                assert(data_copy->cpy_npages > 0);
                    201:                data_m = *page_list;
                    202: 
                    203:                assert( !(data_m == VM_PAGE_NULL || data_m->tabled ||
                    204:                    data_m->error || data_m->absent || data_m->fictitious ||
                    205:                    data_m->restart));
                    206: 
                    207:                /*
                    208:                 *      Look up target page and check its state.
                    209:                 */
                    210: 
                    211: retry_lookup:
                    212:                m = vm_page_lookup(object,offset);
                    213:                was_clustered = FALSE;
                    214:                if (m == VM_PAGE_NULL) {
                    215:                    was_absent = FALSE;
                    216:                }
                    217:                else {
                    218:                    if (m->absent) {
                    219: 
                    220:                        /*
                    221:                         *      Page was requested.  Free the busy
                    222:                         *      page waiting for it.  Insertion
                    223:                         *      of new page happens below.
                    224:                         */
                    225:                        m->list_req_pending = FALSE;
                    226:                        if (m->clustered) {
                    227:                                was_clustered = TRUE;
                    228:                                m->clustered = FALSE;
                    229:                        }
                    230:                        if (m->busy) {
                    231:                                VM_PAGE_FREE(m);
                    232:                        }
                    233:                        was_absent = TRUE;
                    234:                    }
                    235:                    else {
                    236: 
                    237:                        /*
                    238:                         *      Have to wait for page that is busy and
                    239:                         *      not absent.  This is probably going to
                    240:                         *      be an error, but go back and check.
                    241:                         */
                    242:                        if (m->busy) {
                    243:                                PAGE_ASSERT_WAIT(m, THREAD_UNINT);
                    244:                                vm_object_unlock(object);
                    245:                                thread_block((void (*)(void))0);
                    246:                                vm_object_lock(object);
                    247:                                goto retry_lookup;
                    248:                        }
                    249: 
                    250:                        /*
                    251:                         *      Page already present; error.
                    252:                         *      This is an error if data is precious.
                    253:                         */
                    254:                        result = KERN_MEMORY_PRESENT;
                    255:                        error_offset = offset + object->paging_offset;
                    256: 
                    257:                        break;
                    258:                    }
                    259:                }
                    260: 
                    261:                /*
                    262:                 *      Ok to pagein page.  Target object now has no page
                    263:                 *      at offset.  Set the page parameters, then drop
                    264:                 *      in new page and set up pageout state.  Object is
                    265:                 *      still locked here.
                    266:                 *
                    267:                 *      Must clear busy bit in page before inserting it.
                    268:                 *      Ok to skip wakeup logic because nobody else
                    269:                 *      can possibly know about this page.
                    270:                 */
                    271: 
                    272:                data_m->lock_supplied = TRUE;
                    273:                data_m->busy = FALSE;
                    274:                data_m->dirty = FALSE;
                    275:                pmap_clear_modify(data_m->phys_addr);
                    276: 
                    277:                data_m->page_lock = lock_value;
                    278:                if (lock_value != VM_PROT_NONE)
                    279:                        data_m->unusual = TRUE;
                    280:                else
                    281:                        data_m->unusual = FALSE;
                    282: 
                    283:                data_m->unlock_request = VM_PROT_NONE;
                    284:                data_m->precious = precious;
                    285: 
                    286:                data_m->clustered = was_clustered;
                    287: 
                    288:                vm_page_insert(data_m, object, offset);
                    289: 
                    290:                vm_page_lock_queues();
                    291:                if (was_absent)
                    292:                        vm_page_activate(data_m);
                    293:                else
                    294:                        vm_page_deactivate(data_m);
                    295:                vm_page_unlock_queues();
                    296: 
                    297:                /*
                    298:                 *      Null out this page list entry, and advance to next
                    299:                 *      page.
                    300:                 */
                    301: 
                    302:                *page_list++ = VM_PAGE_NULL;
                    303: 
                    304:                if (--(data_copy->cpy_npages) == 0 &&
                    305:                    vm_map_copy_has_cont(data_copy)) {
                    306:                        vm_map_copy_t   new_copy;
                    307: 
                    308:                        vm_object_unlock(object);
                    309:                        vm_map_copy_invoke_cont(data_copy, &new_copy, &result);
                    310:                        vm_object_lock(object);
                    311: 
                    312:                        if (result == KERN_SUCCESS) {
                    313: 
                    314:                            /*
                    315:                             *  Consume on success requires that
                    316:                             *  we keep the original vm_map_copy
                    317:                             *  around in case something fails.
                    318:                             *  Free the old copy if it's not the original
                    319:                             */
                    320:                            if (data_copy != orig_copy) {
                    321:                                vm_map_copy_discard(data_copy);
                    322:                            }
                    323: 
                    324:                            if ((data_copy = new_copy) != VM_MAP_COPY_NULL)
                    325:                                page_list = &data_copy->cpy_page_list[0];
                    326:                        }
                    327:                        else {
                    328:                            error_offset = offset + object->paging_offset +
                    329:                                                PAGE_SIZE;
                    330:                            break;
                    331:                        }
                    332:                }
                    333:        }
                    334: 
                    335:        vm_object_paging_end(object);
                    336: 
                    337:        /*
                    338:         *      If there is a continuation that has not been invoked,
                    339:         *      there must have been an error.  Abort the continuation.
                    340:         */
                    341: 
                    342:        if (data_copy != VM_MAP_COPY_NULL && vm_map_copy_has_cont(data_copy)) {
                    343:                vm_object_unlock(object);
                    344:                vm_map_copy_abort_cont(data_copy);
                    345:                vm_object_lock(object);
                    346:        }
                    347: 
                    348:        /*
                    349:         *      If the pager wants a reply, send it one.
                    350:         */
                    351: 
                    352:        if (IP_VALID(reply_to)) {
                    353:                vm_object_unlock(object);
                    354:                memory_object_supply_completed(
                    355:                                reply_to, reply_to_type,
                    356:                                object->pager_request,
                    357:                                original_offset,
                    358:                                original_length,
                    359:                                result,
                    360:                                error_offset);
                    361:        }
                    362:        else
                    363:                vm_object_unlock(object);
                    364: 
                    365:        vm_object_deallocate(object);
                    366: 
                    367:        /*
                    368:         *      Consume on success:  The final data copy must be
                    369:         *      discarded if it is not the original.  The original
                    370:         *      gets discarded only if this routine succeeds.
                    371:         */
                    372:        if (data_copy != VM_MAP_COPY_NULL &&
                    373:            data_copy != orig_copy)
                    374:                vm_map_copy_discard(data_copy);
                    375:        if (result == KERN_SUCCESS)
                    376:                vm_map_copy_discard(orig_copy);
                    377: 
                    378:        return(result);
                    379: }
                    380: 
                    381: kern_return_t
                    382: memory_object_data_error(
                    383:        vm_object_t     object,
                    384:        vm_offset_t     offset,
                    385:        vm_size_t       size,
                    386:        kern_return_t   error_value)
                    387: {
                    388:         XPR(XPR_MEMORY_OBJECT,
                    389:             "m_o_data_error, object 0x%X, offset 0x%X size 0x%X\n",
                    390:             (integer_t)object, offset, size, 0, 0);
                    391: 
                    392:        if (object == VM_OBJECT_NULL)
                    393:                return(KERN_INVALID_ARGUMENT);
                    394: 
                    395:        if (size != round_page(size)) {
                    396:                vm_object_deallocate(object);
                    397:                return(KERN_INVALID_ARGUMENT);
                    398:        }
                    399: 
                    400:        vm_object_lock(object);
                    401:        offset -= object->paging_offset;
                    402: 
                    403:        while (size != 0) {
                    404:                register vm_page_t m;
                    405: 
                    406:                m = vm_page_lookup(object, offset);
                    407:                if ((m != VM_PAGE_NULL) && m->busy && m->absent) {
                    408:                        if (error_value == KERN_MEMORY_DATA_MOVED) {
                    409:                                m->restart = TRUE;
                    410:                        } else {
                    411:                                if (error_value > KERN_RETURN_MAX) {
                    412:                                        m->page_error = error_value;
                    413:                                } else {
                    414:                                        m->page_error = KERN_MEMORY_ERROR;
                    415:                                }
                    416:                                m->error = TRUE;
                    417:                        }
                    418: 
                    419:                        /*
                    420:                         *      m->unusual was true because page was absent.
                    421:                         *      It remains true because page is either error
                    422:                         *      or restart.
                    423:                         */
                    424:                        m->absent = FALSE;
                    425:                        vm_object_absent_release(object);
                    426: 
                    427:                        PAGE_WAKEUP_DONE(m);
                    428: 
                    429:                        /*
                    430:                         * If this page was not requested (clustered is set),
                    431:                         * then throw it away since there is no one to which
                    432:                         * an error can be reported.
                    433:                         */
                    434:                        vm_page_lock_queues();
                    435:                        if (m->clustered)
                    436:                                vm_page_free(m);
                    437:                        else
                    438:                                vm_page_activate(m);
                    439:                        vm_page_unlock_queues();
                    440:                }
                    441: 
                    442:                size -= PAGE_SIZE;
                    443:                offset += PAGE_SIZE;
                    444:         }
                    445:        vm_object_unlock(object);
                    446: 
                    447:        vm_object_deallocate(object);
                    448:        return(KERN_SUCCESS);
                    449: }
                    450: 
                    451: kern_return_t
                    452: memory_object_data_unavailable(
                    453:        vm_object_t     object,
                    454:        vm_offset_t     offset,
                    455:        vm_size_t       size)
                    456: {
                    457:         XPR(XPR_MEMORY_OBJECT,
                    458:             "m_o_data_unavailable, object 0x%X, offset 0x%X size 0x%X\n",
                    459:             (integer_t)object, offset, size, 0, 0);
                    460: 
                    461:        if (object == VM_OBJECT_NULL)
                    462:                return(KERN_INVALID_ARGUMENT);
                    463: 
                    464:        if (size != round_page(size)) {
                    465:                vm_object_deallocate(object);
                    466:                return(KERN_INVALID_ARGUMENT);
                    467:        }
                    468: 
                    469:        vm_object_lock(object);
                    470:        offset -= object->paging_offset;
                    471: 
                    472:        while (size != 0) {
                    473:                register vm_page_t m;
                    474: 
                    475:                /*
                    476:                 *      We're looking for pages that are both busy and
                    477:                 *      absent (waiting to be filled), converting them
                    478:                 *      to just absent.
                    479:                 *
                    480:                 *      Pages that are just busy can be ignored entirely.
                    481:                 */
                    482: 
                    483:                m = vm_page_lookup(object, offset);
                    484:                if (m == VM_PAGE_NULL) {
                    485:                        if (object->absent_count < vm_object_absent_max)
                    486:                                m = vm_page_grab_fictitious();
                    487:                        if (m != VM_PAGE_NULL) {
                    488:                                m->absent = TRUE;
                    489:                                m->unusual = TRUE;
                    490:                                m->clustered = FALSE;
                    491:                                object->absent_count++;
                    492:                                vm_page_lock_queues();
                    493:                                vm_page_insert(m, object, offset);
                    494:                                vm_page_activate(m);
                    495:                                vm_page_unlock_queues();
                    496:                                PAGE_WAKEUP_DONE(m);
                    497:                        }
                    498:                } else if (m->busy && m->absent) {
                    499:                        /* only consider real pageins in clustering stats */
                    500:                        m->clustered = FALSE;
                    501: 
                    502:                        PAGE_WAKEUP_DONE(m);
                    503: 
                    504:                        vm_page_lock_queues();
                    505:                        vm_page_activate(m);
                    506:                        vm_page_unlock_queues();
                    507:                }
                    508:                size -= PAGE_SIZE;
                    509:                offset += PAGE_SIZE;
                    510:        }
                    511: 
                    512:        vm_object_unlock(object);
                    513: 
                    514:        vm_object_deallocate(object);
                    515:        return(KERN_SUCCESS);
                    516: }
                    517: 
                    518: /*
                    519:  *     Routine:        memory_object_should_return_page
                    520:  *
                    521:  *     Description:
                    522:  *             Determine whether the given page should be returned,
                    523:  *             based on the page's state and on the given return policy.
                    524:  *
                    525:  *             We should return the page if one of the following is true:
                    526:  *
                    527:  *             1. Page is dirty and should_return is not RETURN_NONE.
                    528:  *             2. Page is precious and should_return is RETURN_ALL.
                    529:  *             3. Should_return is RETURN_ANYTHING.
                    530:  *
                    531:  *             As a side effect, m->dirty will be made consistent
                    532:  *             with pmap_is_modified(m), if should_return is not
                    533:  *             MEMORY_OBJECT_RETURN_NONE.
                    534:  */
                    535: 
                    536: #define        memory_object_should_return_page(m, should_return) \
                    537:     (should_return != MEMORY_OBJECT_RETURN_NONE && \
                    538:      (((m)->dirty || ((m)->dirty = pmap_is_modified((m)->phys_addr))) || \
                    539:       ((m)->precious && (should_return) == MEMORY_OBJECT_RETURN_ALL) || \
                    540:       (should_return) == MEMORY_OBJECT_RETURN_ANYTHING))
                    541: 
                    542: typedef        int     memory_object_lock_result_t;
                    543: 
                    544: #define MEMORY_OBJECT_LOCK_RESULT_DONE          0
                    545: #define MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK    1
                    546: #define MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN    2
                    547: #define MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN   3
                    548: 
                    549: memory_object_lock_result_t memory_object_lock_page(
                    550:                                vm_page_t               m,
                    551:                                memory_object_return_t  should_return,
                    552:                                boolean_t               should_flush,
                    553:                                vm_prot_t               prot);
                    554: 
                    555: /*
                    556:  *     Routine:        memory_object_lock_page
                    557:  *
                    558:  *     Description:
                    559:  *             Perform the appropriate lock operations on the
                    560:  *             given page.  See the description of
                    561:  *             "memory_object_lock_request" for the meanings
                    562:  *             of the arguments.
                    563:  *
                    564:  *             Returns an indication that the operation
                    565:  *             completed, blocked, or that the page must
                    566:  *             be cleaned.
                    567:  */
                    568: memory_object_lock_result_t
                    569: memory_object_lock_page(
                    570:        vm_page_t               m,
                    571:        memory_object_return_t  should_return,
                    572:        boolean_t               should_flush,
                    573:        vm_prot_t               prot)
                    574: {
                    575:         XPR(XPR_MEMORY_OBJECT,
                    576:             "m_o_lock_page, page 0x%X rtn %d flush %d prot %d\n",
                    577:             (integer_t)m, should_return, should_flush, prot, 0);
                    578: 
                    579:        /*
                    580:         *      Don't worry about pages for which the kernel
                    581:         *      does not have any data.
                    582:         */
                    583: 
                    584:        if (m->absent || m->error || m->restart)
                    585:                return(MEMORY_OBJECT_LOCK_RESULT_DONE);
                    586: 
                    587:        /*
                    588:         *      If we cannot change access to the page,
                    589:         *      either because a mapping is in progress
                    590:         *      (busy page) or because a mapping has been
                    591:         *      wired, then give up.
                    592:         */
                    593: 
                    594:        if (m->busy)
                    595:                return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
                    596: 
                    597:        assert(!m->fictitious);
                    598: 
                    599:        if (m->wire_count != 0) {
                    600:                /*
                    601:                 *      If no change would take place
                    602:                 *      anyway, return successfully.
                    603:                 *
                    604:                 *      No change means:
                    605:                 *              Not flushing AND
                    606:                 *              No change to page lock [2 checks]  AND
                    607:                 *              Should not return page
                    608:                 *
                    609:                 * XXX  This doesn't handle sending a copy of a wired
                    610:                 * XXX  page to the pager, but that will require some
                    611:                 * XXX  significant surgery.
                    612:                 */
                    613:                if (!should_flush &&
                    614:                    (m->page_lock == prot || prot == VM_PROT_NO_CHANGE) &&
                    615:                    ! memory_object_should_return_page(m, should_return)) {
                    616: 
                    617:                        /*
                    618:                         *      Restart page unlock requests,
                    619:                         *      even though no change took place.
                    620:                         *      [Memory managers may be expecting
                    621:                         *      to see new requests.]
                    622:                         */
                    623:                        m->unlock_request = VM_PROT_NONE;
                    624:                        PAGE_WAKEUP(m);
                    625: 
                    626:                        return(MEMORY_OBJECT_LOCK_RESULT_DONE);
                    627:                }
                    628: 
                    629:                return(MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK);
                    630:        }
                    631: 
                    632:        /*
                    633:         *      If the page is to be flushed, allow
                    634:         *      that to be done as part of the protection.
                    635:         */
                    636: 
                    637:        if (should_flush)
                    638:                prot = VM_PROT_ALL;
                    639: 
                    640:        /*
                    641:         *      Set the page lock.
                    642:         *
                    643:         *      If we are decreasing permission, do it now;
                    644:         *      let the fault handler take care of increases
                    645:         *      (pmap_page_protect may not increase protection).
                    646:         */
                    647: 
                    648:        if (prot != VM_PROT_NO_CHANGE) {
                    649:                if ((m->page_lock ^ prot) & prot) {
                    650:                        pmap_page_protect(m->phys_addr, VM_PROT_ALL & ~prot);
                    651:                }
                    652:                m->page_lock = prot;
                    653:                m->lock_supplied = TRUE;
                    654:                if (prot != VM_PROT_NONE)
                    655:                        m->unusual = TRUE;
                    656:                else
                    657:                        m->unusual = FALSE;
                    658: 
                    659:                /*
                    660:                 *      Restart any past unlock requests, even if no
                    661:                 *      change resulted.  If the manager explicitly
                    662:                 *      requested no protection change, then it is assumed
                    663:                 *      to be remembering past requests.
                    664:                 */
                    665: 
                    666:                m->unlock_request = VM_PROT_NONE;
                    667:                PAGE_WAKEUP(m);
                    668:        }
                    669: 
                    670:        /*
                    671:         *      Handle page returning.
                    672:         */
                    673: 
                    674:        if (memory_object_should_return_page(m, should_return)) {
                    675: 
                    676:                /*
                    677:                 *      If we weren't planning
                    678:                 *      to flush the page anyway,
                    679:                 *      we may need to remove the
                    680:                 *      page from the pageout
                    681:                 *      system and from physical
                    682:                 *      maps now.
                    683:                 */
                    684:                
                    685:                vm_page_lock_queues();
                    686:                VM_PAGE_QUEUES_REMOVE(m);
                    687:                vm_page_unlock_queues();
                    688: 
                    689:                if (!should_flush)
                    690:                        pmap_page_protect(m->phys_addr, VM_PROT_NONE);
                    691: 
                    692:                if (m->dirty)
                    693:                        return(MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN);
                    694:                else
                    695:                        return(MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN);
                    696:        }
                    697: 
                    698:        /*
                    699:         *      Handle flushing
                    700:         */
                    701: 
                    702:        if (should_flush) {
                    703:                VM_PAGE_FREE(m);
                    704:        } else {
                    705:                extern boolean_t vm_page_deactivate_hint;
                    706: 
                    707:                /*
                    708:                 *      XXX Make clean but not flush a paging hint,
                    709:                 *      and deactivate the pages.  This is a hack
                    710:                 *      because it overloads flush/clean with
                    711:                 *      implementation-dependent meaning.  This only
                    712:                 *      happens to pages that are already clean.
                    713:                 */
                    714: 
                    715:                if (vm_page_deactivate_hint &&
                    716:                    (should_return != MEMORY_OBJECT_RETURN_NONE)) {
                    717:                        vm_page_lock_queues();
                    718:                        vm_page_deactivate(m);
                    719:                        vm_page_unlock_queues();
                    720:                }
                    721:        }
                    722: 
                    723:        return(MEMORY_OBJECT_LOCK_RESULT_DONE);
                    724: }
                    725: #define LIST_REQ_PAGEOUT_PAGES(object, new_object, new_offset, action, po) \
                    726: MACRO_BEGIN                                                            \
                    727:                                                                        \
                    728:        register int            i;                                      \
                    729:        register vm_page_t      hp;                                     \
                    730:                                                                        \
                    731:        vm_object_unlock(object);                                       \
                    732:                                                                        \
                    733:        if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) ==   \
                    734:        ((rpc_subsystem_t) &vnode_pager_workaround)) {                  \
                    735:                        (void) vnode_pager_data_return(object->pager,           \
                    736:                object->pager_request,                                  \
                    737:                po,                                                     \
                    738:                POINTER_T(0),                                           \
                    739:                new_offset,                                             \
                    740:                (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN),       \
                    741:                !should_flush);                                         \
                    742:        } else {                                                        \
                    743:                (void) memory_object_data_return(object->pager,         \
                    744:                object->pager_request,                                  \
                    745:                po,                                                     \
                    746:                POINTER_T(0),                                           \
                    747:                new_offset,                                             \
                    748:                (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN),       \
                    749:                !should_flush);                                         \
                    750:        }                                                               \
                    751:                                                                        \
                    752:        vm_object_lock(object);                                         \
                    753:                                                                        \
                    754:         new_object = VM_OBJECT_NULL;                                   \
                    755: MACRO_END
                    756: 
                    757: #ifdef MACH_BSD
                    758: #define PAGEOUT_PAGES(object, new_object, new_offset, action, po)      \
                    759: MACRO_BEGIN                                                            \
                    760:                                                                        \
                    761:        vm_map_copy_t           copy;                                   \
                    762:        register int            i;                                      \
                    763:        register vm_page_t      hp;                                     \
                    764:                                                                        \
                    765:        vm_object_unlock(object);                                       \
                    766:                                                                        \
                    767:        (void) vm_map_copyin_object(new_object, 0, new_offset, &copy);  \
                    768:                                                                        \
                    769:        if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) ==   \
                    770:        ((rpc_subsystem_t) &vnode_pager_workaround)) {                  \
                    771:                        (void) vnode_pager_data_return(object->pager,           \
                    772:                object->pager_request,                                  \
                    773:                po,                                                     \
                    774:                POINTER_T(copy),                                        \
                    775:                new_offset,                                             \
                    776:                (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN),       \
                    777:                !should_flush);                                         \
                    778:        } else {                                                        \
                    779:                (void) memory_object_data_return(object->pager,         \
                    780:                object->pager_request,                                  \
                    781:                po,                                                     \
                    782:                POINTER_T(copy),                                        \
                    783:                new_offset,                                             \
                    784:                (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN),       \
                    785:                !should_flush);                                         \
                    786:        }                                                               \
                    787:                                                                        \
                    788:        vm_object_lock(object);                                         \
                    789:                                                                        \
                    790:        for (i = 0; i < atop(new_offset); i++) {                        \
                    791:                hp = holding_pages[i];                                  \
                    792:                if (hp != VM_PAGE_NULL) {                               \
                    793:                        vm_object_paging_end(object);                   \
                    794:                        VM_PAGE_FREE(hp);                               \
                    795:                }                                                       \
                    796:        }                                                               \
                    797:                                                                        \
                    798:         new_object = VM_OBJECT_NULL;                                   \
                    799: MACRO_END
                    800: #else
                    801: #define PAGEOUT_PAGES(object, new_object, new_offset, action, po)      \
                    802: MACRO_BEGIN                                                            \
                    803:                                                                        \
                    804:        vm_map_copy_t           copy;                                   \
                    805:        register int            i;                                      \
                    806:        register vm_page_t      hp;                                     \
                    807:                                                                        \
                    808:        vm_object_unlock(object);                                       \
                    809:                                                                        \
                    810:        (void) vm_map_copyin_object(new_object, 0, new_offset, &copy);  \
                    811:                                                                        \
                    812:        (void) memory_object_data_return(                               \
                    813:                        object->pager,                                  \
                    814:                        object->pager_request,                          \
                    815:                        po,                                             \
                    816:                        POINTER_T(copy),                                \
                    817:                        new_offset,                                     \
                    818:                (action == MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN),       \
                    819:                        !should_flush);                                 \
                    820:                                                                        \
                    821:        vm_object_lock(object);                                         \
                    822:                                                                        \
                    823:        for (i = 0; i < atop(new_offset); i++) {                        \
                    824:                hp = holding_pages[i];                                  \
                    825:                if (hp != VM_PAGE_NULL) {                               \
                    826:                        vm_object_paging_end(object);                   \
                    827:                        VM_PAGE_FREE(hp);                               \
                    828:                }                                                       \
                    829:        }                                                               \
                    830:                                                                        \
                    831:         new_object = VM_OBJECT_NULL;                                   \
                    832: MACRO_END
                    833: #endif
                    834: 
                    835: /*
                    836:  *     Routine:        memory_object_lock_request [user interface]
                    837:  *
                    838:  *     Description:
                    839:  *             Control use of the data associated with the given
                    840:  *             memory object.  For each page in the given range,
                    841:  *             perform the following operations, in order:
                    842:  *                     1)  restrict access to the page (disallow
                    843:  *                         forms specified by "prot");
                    844:  *                     2)  return data to the manager (if "should_return"
                    845:  *                         is RETURN_DIRTY and the page is dirty, or
                    846:  *                         "should_return" is RETURN_ALL and the page
                    847:  *                         is either dirty or precious); and,
                    848:  *                     3)  flush the cached copy (if "should_flush"
                    849:  *                         is asserted).
                    850:  *             The set of pages is defined by a starting offset
                    851:  *             ("offset") and size ("size").  Only pages with the
                    852:  *             same page alignment as the starting offset are
                    853:  *             considered.
                    854:  *
                    855:  *             A single acknowledgement is sent (to the "reply_to"
                    856:  *             port) when these actions are complete.  If successful,
                    857:  *             the naked send right for reply_to is consumed.
                    858:  */
                    859: 
                    860: kern_return_t
                    861: memory_object_lock_request(
                    862:        register vm_object_t    object,
                    863:        register vm_offset_t    offset,
                    864:        register vm_size_t      size,
                    865:        memory_object_return_t  should_return,
                    866:        boolean_t               should_flush,
                    867:        vm_prot_t               prot,
                    868:        ipc_port_t              reply_to,
                    869:        mach_msg_type_name_t    reply_to_type)
                    870: {
                    871:        vm_offset_t             original_offset = offset;
                    872: 
                    873:         XPR(XPR_MEMORY_OBJECT,
                    874:            "m_o_lock_request, obj 0x%X off 0x%X size 0x%X flags %X prot %X\n",
                    875:            (integer_t)object, offset, size, 
                    876:            (((should_return&1)<<1)|should_flush), prot);
                    877: 
                    878:        /*
                    879:         *      Check for bogus arguments.
                    880:         */
                    881:        if (object == VM_OBJECT_NULL)
                    882:                return (KERN_INVALID_ARGUMENT);
                    883: 
                    884:        if ((prot & ~VM_PROT_ALL) != 0 && prot != VM_PROT_NO_CHANGE) {
                    885:                vm_object_deallocate(object);
                    886:                return (KERN_INVALID_ARGUMENT);
                    887:        }
                    888: 
                    889:        size = round_page(size);
                    890: 
                    891:        /*
                    892:         *      Lock the object, and acquire a paging reference to
                    893:         *      prevent the memory_object and control ports from
                    894:         *      being destroyed.
                    895:         */
                    896: 
                    897:        vm_object_lock(object);
                    898:        vm_object_paging_begin(object);
                    899:        offset -= object->paging_offset;
                    900: 
                    901:        (void)memory_object_update(object,
                    902:                offset, size, should_return, should_flush, prot);
                    903: 
                    904:        if (IP_VALID(reply_to)) {
                    905:                vm_object_unlock(object);
                    906: 
                    907:                /* consumes our naked send-once/send right for reply_to */
                    908:                (void) memory_object_lock_completed(reply_to, reply_to_type,
                    909:                        object->pager_request, original_offset, size);
                    910: 
                    911:                vm_object_lock(object);
                    912:        }
                    913: 
                    914:        vm_object_paging_end(object);
                    915:        vm_object_unlock(object);
                    916:        vm_object_deallocate(object);
                    917: 
                    918:        return (KERN_SUCCESS);
                    919: }
                    920: 
                    921: /*
                    922:  *     Routine:        memory_object_sync
                    923:  *
                    924:  *     Kernel internal function to synch out pages in a given
                    925:  *     range within an object to its memory manager.  Much the
                    926:  *     same as memory_object_lock_request but page protection
                    927:  *     is not changed.
                    928:  *
                    929:  *     If the should_flush and should_return flags are true pages
                    930:  *     are flushed, that is dirty & precious pages are written to
                    931:  *     the memory manager and then discarded.  If should_return
                    932:  *     is false, only precious pages are returned to the memory
                    933:  *     manager.
                    934:  *
                    935:  *     If should flush is false and should_return true, the memory
                    936:  *     manager's copy of the pages is updated.  If should_return
                    937:  *     is also false, only the precious pages are updated.  This
                    938:  *     last option is of limited utility.
                    939:  *
                    940:  *     Returns:
                    941:  *     FALSE           if no pages were returned to the pager
                    942:  *     TRUE            otherwise.
                    943:  */
                    944: 
                    945: boolean_t
                    946: memory_object_sync(
                    947:        vm_object_t     object,
                    948:        vm_offset_t     offset,
                    949:        vm_size_t       size,
                    950:        boolean_t       should_flush,
                    951:        boolean_t       should_return)
                    952: {
                    953:        boolean_t       rv;
                    954: 
                    955:         XPR(XPR_MEMORY_OBJECT,
                    956:             "m_o_sync, object 0x%X, offset 0x%X size 0x%x flush %d rtn %d\n",
                    957:             (integer_t)object, offset, size, should_flush, should_return);
                    958: 
                    959:        /*
                    960:         * Lock the object, and acquire a paging reference to
                    961:         * prevent the memory_object and control ports from
                    962:         * being destroyed.
                    963:         */
                    964:        vm_object_lock(object);
                    965:        vm_object_paging_begin(object);
                    966: 
                    967:        rv = memory_object_update(object, offset, size,
                    968:                (should_return) ?
                    969:                        MEMORY_OBJECT_RETURN_ALL :
                    970:                        MEMORY_OBJECT_RETURN_NONE,
                    971:                should_flush,
                    972:                VM_PROT_NO_CHANGE);
                    973: 
                    974: 
                    975:        vm_object_paging_end(object);
                    976:        vm_object_unlock(object);
                    977:        return rv;
                    978: }
                    979: 
                    980: /*
                    981:  *     Routine:        memory_object_update
                    982:  *     Description:
                    983:  *             Work function for m_o_lock_request(), m_o_sync().
                    984:  *
                    985:  *             Called with object locked and paging ref taken.
                    986:  */
                    987: kern_return_t
                    988: memory_object_update(
                    989:        register vm_object_t    object,
                    990:        register vm_offset_t    offset,
                    991:        register vm_size_t      size,
                    992:        memory_object_return_t  should_return,
                    993:        boolean_t               should_flush,
                    994:        vm_prot_t               prot)
                    995: {
                    996:        register vm_page_t      m;
                    997:        vm_page_t               holding_page;
                    998:        vm_size_t               original_size = size;
                    999:        vm_offset_t             paging_offset = 0;
                   1000:        vm_object_t             new_object = VM_OBJECT_NULL;
                   1001:        vm_object_t             copy_object;
                   1002:        vm_offset_t             new_offset = 0;
                   1003:        vm_offset_t             last_offset = offset;
                   1004:        memory_object_lock_result_t     page_lock_result;
                   1005:        memory_object_lock_result_t     pageout_action;
                   1006:        vm_page_t               holding_pages[DATA_WRITE_MAX];
                   1007:        boolean_t               data_returned = FALSE;
                   1008: #ifndef NOT_LIST_REQ
                   1009:        boolean_t               pending_pageout = FALSE;
                   1010: #endif
                   1011: 
                   1012:        /*
                   1013:         *      To avoid blocking while scanning for pages, save
                   1014:         *      dirty pages to be cleaned all at once.
                   1015:         *
                   1016:         *      XXXO A similar strategy could be used to limit the
                   1017:         *      number of times that a scan must be restarted for
                   1018:         *      other reasons.  Those pages that would require blocking
                   1019:         *      could be temporarily collected in another list, or
                   1020:         *      their offsets could be recorded in a small array.
                   1021:         */
                   1022: 
                   1023:        /*
                   1024:         * XXX  NOTE: May want to consider converting this to a page list
                   1025:         * XXX  vm_map_copy interface.  Need to understand object
                   1026:         * XXX  coalescing implications before doing so.
                   1027:         */
                   1028: 
                   1029: 
                   1030:        if(((copy_object = object->copy) != NULL) && should_flush) {
                   1031:                vm_size_t       i;
                   1032:                vm_size_t       copy_size;
                   1033:                vm_offset_t     copy_offset;
                   1034:                vm_prot_t       prot;
                   1035:                vm_page_t       page;
                   1036:                vm_page_t       top_page;
                   1037:                kern_return_t   error = 0;
                   1038: 
                   1039: 
                   1040: 
                   1041:                /* translate offset with respect to shadow's offset */
                   1042:                copy_offset = (offset >= copy_object->shadow_offset)?
                   1043:                        offset - copy_object->shadow_offset :
                   1044:                        (vm_offset_t)0;
                   1045:                if(copy_offset > copy_object->size)
                   1046:                        copy_offset = copy_object->size;
                   1047: 
                   1048:                /* clip size with respect to shadow offset */
                   1049:                copy_size = (offset >= copy_object->shadow_offset) ?
                   1050:                        size : size - (copy_object->shadow_offset - offset);
                   1051: 
                   1052:                if(copy_size <= 0) {
                   1053:                        copy_size = 0;
                   1054:                } else {
                   1055:                        copy_size = ((copy_offset + copy_size) 
                   1056:                                <= copy_object->size) ?
                   1057:                                copy_size : copy_object->size - copy_offset;
                   1058:                }
                   1059:                /* check for a copy_offset which is beyond the end of */
                   1060:                /* the copy_object */
                   1061:                if(copy_size < 0)
                   1062:                        copy_size = 0;
                   1063: 
                   1064:                vm_object_unlock(object);
                   1065:                vm_object_lock(copy_object);
                   1066:                vm_object_paging_begin(copy_object);
                   1067:                for (i=copy_offset; i<copy_size; i+=PAGE_SIZE) {
                   1068:        RETRY_COW_OF_LOCK_REQUEST:
                   1069:                        prot =  VM_PROT_WRITE|VM_PROT_READ;
                   1070:                        switch (vm_fault_page(copy_object, i, 
                   1071:                                VM_PROT_WRITE|VM_PROT_READ,
                   1072:                                FALSE,
                   1073:                                THREAD_UNINT,
                   1074:                                copy_offset,
                   1075:                                copy_offset+copy_size,
                   1076:                                VM_BEHAVIOR_SEQUENTIAL,
                   1077:                                &prot,
                   1078:                                &page,
                   1079:                                &top_page,
                   1080:                                (int *)0,
                   1081:                                &error,
                   1082:                                FALSE,
                   1083:                                FALSE)) {
                   1084: 
                   1085:                        case VM_FAULT_SUCCESS:
                   1086:                                if(top_page) {
                   1087:                                        vm_fault_cleanup(
                   1088:                                                page->object, top_page);
                   1089:                                        PAGE_WAKEUP_DONE(page);
                   1090:                                        vm_page_lock_queues();
                   1091:                                        if (!page->active && !page->inactive)
                   1092:                                                vm_page_activate(page);
                   1093:                                        vm_page_unlock_queues();
                   1094:                                        vm_object_lock(copy_object);
                   1095:                                        vm_object_paging_begin(copy_object);
                   1096:                                } else {
                   1097:                                        PAGE_WAKEUP_DONE(page);
                   1098:                                        vm_page_lock_queues();
                   1099:                                        if (!page->active && !page->inactive)
                   1100:                                                vm_page_activate(page);
                   1101:                                        vm_page_unlock_queues();
                   1102:                                }
                   1103:                                break;
                   1104:                        case VM_FAULT_RETRY:
                   1105:                                prot =  VM_PROT_WRITE|VM_PROT_READ;
                   1106:                                vm_object_lock(copy_object);
                   1107:                                vm_object_paging_begin(copy_object);
                   1108:                                goto RETRY_COW_OF_LOCK_REQUEST;
                   1109:                        case VM_FAULT_INTERRUPTED:
                   1110:                                prot =  VM_PROT_WRITE|VM_PROT_READ;
                   1111:                                vm_object_lock(copy_object);
                   1112:                                vm_object_paging_begin(copy_object);
                   1113:                                goto RETRY_COW_OF_LOCK_REQUEST;
                   1114:                        case VM_FAULT_MEMORY_SHORTAGE:
                   1115:                                VM_PAGE_WAIT();
                   1116:                                prot =  VM_PROT_WRITE|VM_PROT_READ;
                   1117:                                vm_object_lock(copy_object);
                   1118:                                vm_object_paging_begin(copy_object);
                   1119:                                goto RETRY_COW_OF_LOCK_REQUEST;
                   1120:                        case VM_FAULT_FICTITIOUS_SHORTAGE:
                   1121:                                vm_page_more_fictitious();
                   1122:                                prot =  VM_PROT_WRITE|VM_PROT_READ;
                   1123:                                vm_object_lock(copy_object);
                   1124:                                vm_object_paging_begin(copy_object);
                   1125:                                goto RETRY_COW_OF_LOCK_REQUEST;
                   1126:                        case VM_FAULT_MEMORY_ERROR:
                   1127:                                vm_object_lock(object);
                   1128:                                goto BYPASS_COW_COPYIN;
                   1129:                        }
                   1130:                                
                   1131: 
                   1132:                }
                   1133:                vm_object_paging_end(copy_object);
                   1134:                vm_object_unlock(copy_object);
                   1135:                vm_object_lock(object);
                   1136:        }
                   1137: BYPASS_COW_COPYIN:
                   1138: 
                   1139:        for (;
                   1140:             size != 0;
                   1141:             size -= PAGE_SIZE, offset += PAGE_SIZE)
                   1142:        {
                   1143:            /*
                   1144:             *  Limit the number of pages to be cleaned at once.
                   1145:             */
                   1146: #ifdef NOT_LIST_REQ
                   1147:            if (new_object != VM_OBJECT_NULL &&
                   1148:                    new_offset >= PAGE_SIZE * DATA_WRITE_MAX)
                   1149:            {
                   1150:                PAGEOUT_PAGES(object, new_object, new_offset, pageout_action,
                   1151:                                paging_offset);
                   1152:            }
                   1153: #else 
                   1154: /*
                   1155:        if(((rpc_subsystem_t)pager_mux_hash_lookup(object->pager)) !=
                   1156:                                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1157:            if (new_object != VM_OBJECT_NULL &&
                   1158:                    new_offset >= PAGE_SIZE * DATA_WRITE_MAX)
                   1159:            {
                   1160:                PAGEOUT_PAGES(object, new_object, new_offset, pageout_action,
                   1161:                                paging_offset);
                   1162:            }
                   1163:        } else {
                   1164: */
                   1165:            if (pending_pageout &&
                   1166:                    new_offset >= PAGE_SIZE * DATA_WRITE_MAX)
                   1167:            {
                   1168:                LIST_REQ_PAGEOUT_PAGES(object, new_object, 
                   1169:                                new_offset, 
                   1170:                                pageout_action, paging_offset);
                   1171:                pending_pageout = FALSE;
                   1172:            }
                   1173: /*
                   1174:        }
                   1175: */
                   1176: #endif
                   1177: 
                   1178:            while ((m = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
                   1179:                page_lock_result = memory_object_lock_page(m, should_return,
                   1180:                                        should_flush, prot);
                   1181: 
                   1182:                XPR(XPR_MEMORY_OBJECT,
                   1183:                     "m_o_update: lock_page, obj 0x%X offset 0x%X result %d\n",
                   1184:                     (integer_t)object, offset, page_lock_result, 0, 0);
                   1185: 
                   1186:                switch (page_lock_result)
                   1187:                {
                   1188:                    case MEMORY_OBJECT_LOCK_RESULT_DONE:
                   1189:                        /*
                   1190:                         *      End of a cluster of dirty pages.
                   1191:                         */
                   1192: #ifdef NOT_LIST_REQ
                   1193:                        if (new_object != VM_OBJECT_NULL) {
                   1194:                            PAGEOUT_PAGES(object, new_object, new_offset,
                   1195:                                        pageout_action, paging_offset);
                   1196:                            continue;
                   1197:                        }
                   1198: #else
                   1199: /*
                   1200:        if(((rpc_subsystem_t) pager_mux_hash_lookup(object->pager)) !=
                   1201:                                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1202:                        if (new_object != VM_OBJECT_NULL) {
                   1203:                            PAGEOUT_PAGES(object, new_object, new_offset,
                   1204:                                        pageout_action, paging_offset);
                   1205:                            continue;
                   1206:                        }
                   1207:        } else {
                   1208: */
                   1209:                        if(pending_pageout) {
                   1210:                                LIST_REQ_PAGEOUT_PAGES(object, new_object, 
                   1211:                                        new_offset, pageout_action, 
                   1212:                                        paging_offset);
                   1213:                                pending_pageout = FALSE;
                   1214:                                continue;
                   1215:                        }
                   1216: /*
                   1217:        }
                   1218: */
                   1219: #endif
                   1220:                        break;
                   1221: 
                   1222:                    case MEMORY_OBJECT_LOCK_RESULT_MUST_BLOCK:
                   1223:                        /*
                   1224:                         *      Since it is necessary to block,
                   1225:                         *      clean any dirty pages now.
                   1226:                         */
                   1227: #ifdef NOT_LIST_REQ
                   1228:                        if (new_object != VM_OBJECT_NULL) {
                   1229:                            PAGEOUT_PAGES(object, new_object, new_offset,
                   1230:                                        pageout_action, paging_offset);
                   1231:                            continue;
                   1232:                        }
                   1233: #else
                   1234: /*
                   1235:        if(((rpc_subsystem_t) pager_mux_hash_lookup(object->pager)) !=
                   1236:                                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1237:                        if (new_object != VM_OBJECT_NULL) {
                   1238:                            PAGEOUT_PAGES(object, new_object, new_offset,
                   1239:                                        pageout_action, paging_offset);
                   1240:                            continue;
                   1241:                        }
                   1242:        } else {
                   1243: */
                   1244:                        if(pending_pageout) {
                   1245:                                LIST_REQ_PAGEOUT_PAGES(object, new_object, 
                   1246:                                        new_offset, pageout_action, 
                   1247:                                        paging_offset);
                   1248:                                pending_pageout = FALSE;
                   1249:                                continue;
                   1250:                        }
                   1251: /*
                   1252:        }
                   1253: */
                   1254: #endif
                   1255: 
                   1256:                        PAGE_ASSERT_WAIT(m, THREAD_UNINT);
                   1257:                        vm_object_unlock(object);
                   1258:                        thread_block((void (*)(void))0);
                   1259:                        vm_object_lock(object);
                   1260:                        continue;
                   1261: 
                   1262:                    case MEMORY_OBJECT_LOCK_RESULT_MUST_CLEAN:
                   1263:                    case MEMORY_OBJECT_LOCK_RESULT_MUST_RETURN:
                   1264:                        /*
                   1265:                         * The clean and return cases are similar.
                   1266:                         *
                   1267:                         */
                   1268: 
                   1269:                        /*
                   1270:                         * if this would form a discontiguous block,
                   1271:                         * clean the old pages and start anew.
                   1272:                         *
                   1273:                         * NOTE: The first time through here, new_object
                   1274:                         * is null, hiding the fact that pageout_action
                   1275:                         * is not initialized.
                   1276:                         */
                   1277: #ifdef NOT_LIST_REQ
                   1278:                        /*
                   1279:                         * Mark the page busy since we unlock the
                   1280:                         * object below.
                   1281:                         */
                   1282:                        m->busy = TRUE;
                   1283:                        if (new_object != VM_OBJECT_NULL &&
                   1284:                            (last_offset != offset ||
                   1285:                             pageout_action != page_lock_result)) {
                   1286:                                PAGEOUT_PAGES(object, new_object, new_offset,
                   1287:                                                pageout_action, paging_offset);
                   1288:                        }
                   1289:                        vm_object_unlock(object);
                   1290: 
                   1291:                        /*
                   1292:                         *      If we have not already allocated an object
                   1293:                         *      for a range of pages to be written, do so
                   1294:                         *      now.
                   1295:                         */
                   1296:                        if (new_object == VM_OBJECT_NULL) {
                   1297:                                if (should_flush) {
                   1298:                                        /* use clean-in-place if possible */
                   1299:                                        new_object = vm_pageout_object_allocate(
                   1300:                                                        m,
                   1301:                                                        original_size,
                   1302:                                                        m->offset);
                   1303:                                } else {
                   1304:                                        /* do not use clean-in-place */
                   1305:                                        new_object =
                   1306:                                            vm_object_allocate(original_size);
                   1307:                                }
                   1308:                                new_offset = 0;
                   1309:                                paging_offset = m->offset +
                   1310:                                        object->paging_offset;
                   1311:                                pageout_action = page_lock_result;
                   1312:                        }
                   1313: 
                   1314:                        if (should_flush) {
                   1315:                                /*
                   1316:                                 *      Move or shadow the dirty page into the
                   1317:                                 *      new object.
                   1318:                                 *      This applies to either trusted or
                   1319:                                 *      untrusted pagers.
                   1320:                                 *      Get a paging ref to donate to
                   1321:                                 *      vm_pageout_setup().
                   1322:                                 */
                   1323:                                vm_object_lock(object);
                   1324:                                vm_object_paging_begin(object);
                   1325:                                vm_object_unlock(object);
                   1326:                                holding_page = vm_pageout_setup(m,
                   1327:                                                new_object,
                   1328:                                                new_offset);
                   1329:                        } else {
                   1330:                                /*
                   1331:                                 * Clean but do not flush, always
                   1332:                                 * copying the page.  Allowing clean-in-place
                   1333:                                 * is potentially confusing to pagers and XMM
                   1334:                                 * that ask for clean pages, since the page
                   1335:                                 * could become dirty before the pager
                   1336:                                 * looks at it.
                   1337:                                 */
                   1338:                                vm_page_t       new_m;
                   1339: 
                   1340:                                while ((new_m=vm_page_grab()) == VM_PAGE_NULL) {
                   1341:                                        VM_PAGE_WAIT();
                   1342:                                }
                   1343:                                assert(new_m != VM_PAGE_NULL);
                   1344: 
                   1345:                                vm_object_lock(m->object);
                   1346:                                m->busy = FALSE;
                   1347:                                vm_page_lock_queues();
                   1348:                                vm_pageclean_copy(m, new_m, new_object,
                   1349:                                                                new_offset);
                   1350:                                vm_page_unlock_queues();
                   1351:                                vm_object_unlock(m->object);
                   1352:                                holding_page = VM_PAGE_NULL;
                   1353:                        }
                   1354:                        /*
                   1355:                         *      Save the holding page if there is one.
                   1356:                         */
                   1357:                        holding_pages[atop(new_offset)] = holding_page;
                   1358: #else
                   1359: #if 0
                   1360:        if(((rpc_subsystem_t) pager_mux_hash_lookup(object->pager)) !=
                   1361:                                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1362:                        /*
                   1363:                         * Mark the page busy since we unlock the
                   1364:                         * object below.
                   1365:                         */
                   1366:                        m->busy = TRUE;
                   1367:                        if (new_object != VM_OBJECT_NULL &&
                   1368:                            (last_offset != offset ||
                   1369:                             pageout_action != page_lock_result)) {
                   1370:                                PAGEOUT_PAGES(object, new_object, new_offset,
                   1371:                                                pageout_action, paging_offset);
                   1372:                        }
                   1373:                        vm_object_unlock(object);
                   1374: 
                   1375:                        /*
                   1376:                         *      If we have not already allocated an object
                   1377:                         *      for a range of pages to be written, do so
                   1378:                         *      now.
                   1379:                         */
                   1380:                        if (new_object == VM_OBJECT_NULL) {
                   1381:                                if (should_flush) {
                   1382:                                        /* use clean-in-place if possible */
                   1383:                                        new_object = vm_pageout_object_allocate(
                   1384:                                                        m,
                   1385:                                                        original_size,
                   1386:                                                        m->offset);
                   1387:                                } else {
                   1388:                                        /* do not use clean-in-place */
                   1389:                                        new_object =
                   1390:                                            vm_object_allocate(original_size);
                   1391:                                }
                   1392:                                new_offset = 0;
                   1393:                                paging_offset = m->offset +
                   1394:                                        object->paging_offset;
                   1395:                                pageout_action = page_lock_result;
                   1396:                        }
                   1397: 
                   1398:                        if (should_flush) {
                   1399:                                /*
                   1400:                                 *      Move or shadow the dirty page into the
                   1401:                                 *      new object.
                   1402:                                 *      This applies to either trusted or
                   1403:                                 *      untrusted pagers.
                   1404:                                 *      Get a paging ref to donate to
                   1405:                                 *      vm_pageout_setup().
                   1406:                                 */
                   1407:                                vm_object_lock(object);
                   1408:                                vm_object_paging_begin(object);
                   1409:                                vm_object_unlock(object);
                   1410:                                holding_page = vm_pageout_setup(m,
                   1411:                                                new_object,
                   1412:                                                new_offset);
                   1413:                        } else {
                   1414:                                /*
                   1415:                                 * Clean but do not flush, always
                   1416:                                 * copying the page.  Allowing clean-in-place
                   1417:                                 * is potentially confusing to pagers and XMM
                   1418:                                 * that ask for clean pages, since the page
                   1419:                                 * could become dirty before the pager
                   1420:                                 * looks at it.
                   1421:                                 */
                   1422:                                vm_page_t       new_m;
                   1423: 
                   1424:                                while ((new_m=vm_page_grab()) == VM_PAGE_NULL) {
                   1425:                                        VM_PAGE_WAIT();
                   1426:                                }
                   1427:                                assert(new_m != VM_PAGE_NULL);
                   1428: 
                   1429:                                vm_object_lock(m->object);
                   1430:                                m->busy = FALSE;
                   1431:                                vm_page_lock_queues();
                   1432:                                vm_pageclean_copy(m, new_m, new_object,
                   1433:                                                                new_offset);
                   1434:                                vm_page_unlock_queues();
                   1435:                                vm_object_unlock(m->object);
                   1436:                                holding_page = VM_PAGE_NULL;
                   1437:                        }
                   1438:                        /*
                   1439:                         *      Save the holding page if there is one.
                   1440:                         */
                   1441:                        holding_pages[atop(new_offset)] = holding_page;
                   1442:        } else {
                   1443: #endif
                   1444:                        if (pending_pageout &&
                   1445:                            (last_offset != offset ||
                   1446:                             pageout_action != page_lock_result)) {
                   1447:                                LIST_REQ_PAGEOUT_PAGES(object, new_object, 
                   1448:                                                new_offset, pageout_action, 
                   1449:                                                paging_offset);
                   1450:                                pending_pageout = FALSE;
                   1451:                        }
                   1452:                        holding_page = VM_PAGE_NULL;
                   1453:                        if(!pending_pageout) {
                   1454:                                pending_pageout = TRUE;
                   1455:                                pageout_action = page_lock_result;
                   1456:                                paging_offset = offset;
                   1457:                        }
                   1458:                        m->list_req_pending = TRUE;
                   1459:                        m->cleaning = TRUE;
                   1460:                        if (should_flush) {
                   1461:                                m->busy = TRUE;
                   1462:                                m->pageout = TRUE;
                   1463:                        }
                   1464:                        vm_object_unlock(object);
                   1465: /*
                   1466:        }
                   1467: */
                   1468: 
                   1469: #endif
                   1470: 
                   1471:                        new_offset += PAGE_SIZE;
                   1472:                        last_offset = offset + PAGE_SIZE;
                   1473:                        data_returned = TRUE;
                   1474: 
                   1475:                        vm_object_lock(object);
                   1476:                        break;
                   1477:                }
                   1478:                break;
                   1479:            }
                   1480:        }
                   1481: 
                   1482:        /*
                   1483:         *      We have completed the scan for applicable pages.
                   1484:         *      Clean any pages that have been saved.
                   1485:         */
                   1486: #ifdef NOT_LIST_REQ
                   1487:        if (new_object != VM_OBJECT_NULL) {
                   1488:            PAGEOUT_PAGES(object, new_object, new_offset, pageout_action,
                   1489:                        paging_offset);
                   1490:        }
                   1491: #else
                   1492: /*
                   1493:        if(((rpc_subsystem_t) pager_mux_hash_lookup(object->pager)) !=
                   1494:                                ((rpc_subsystem_t) &vnode_pager_workaround)) {
                   1495:        if (new_object != VM_OBJECT_NULL) {
                   1496:            PAGEOUT_PAGES(object, new_object, new_offset, pageout_action,
                   1497:                        paging_offset);
                   1498:        }
                   1499:        } else {
                   1500: */
                   1501:        if (pending_pageout) {
                   1502:            LIST_REQ_PAGEOUT_PAGES(object, new_object, 
                   1503:                                new_offset, pageout_action, paging_offset);
                   1504:        }
                   1505: /*
                   1506:        }
                   1507: */
                   1508: #endif
                   1509:        return (data_returned);
                   1510: }
                   1511: 
                   1512: /*
                   1513:  *     Routine:        memory_object_synchronize_completed [user interface]
                   1514:  *
                   1515:  *     Tell kernel that previously synchronized data
                   1516:  *     (memory_object_synchronize) has been queue or placed on the
                   1517:  *     backing storage.
                   1518:  *
                   1519:  *     Note: there may be multiple synchronize requests for a given
                   1520:  *     memory object outstanding but they will not overlap.
                   1521:  */
                   1522: 
                   1523: kern_return_t
                   1524: memory_object_synchronize_completed(
                   1525:        vm_object_t     object,
                   1526:        vm_offset_t     offset,
                   1527:        vm_offset_t     length)
                   1528: {
                   1529:         msync_req_t             msr;
                   1530: 
                   1531:         XPR(XPR_MEMORY_OBJECT,
                   1532:            "m_o_sync_completed, object 0x%X, offset 0x%X length 0x%X\n",
                   1533:            (integer_t)object, offset, length, 0, 0);
                   1534: 
                   1535:        /*
                   1536:         *      Look for bogus arguments
                   1537:         */
                   1538: 
                   1539:        if (object == VM_OBJECT_NULL) {
                   1540:                return KERN_INVALID_ARGUMENT;
                   1541:        }
                   1542: 
                   1543:        vm_object_lock(object);
                   1544: 
                   1545: /*
                   1546:  *     search for sync request structure
                   1547:  */
                   1548:        queue_iterate(&object->msr_q, msr, msync_req_t, msr_q) {
                   1549:                if (msr->offset == offset && msr->length == length) {
                   1550:                        queue_remove(&object->msr_q, msr, msync_req_t, msr_q);
                   1551:                        break;
                   1552:                }
                   1553:         }/* queue_iterate */
                   1554: 
                   1555:        if (queue_end(&object->msr_q, (queue_entry_t)msr)) {
                   1556:                vm_object_unlock(object);
                   1557:                vm_object_deallocate(object);
                   1558:                return KERN_INVALID_ARGUMENT;
                   1559:        }
                   1560: 
                   1561:        msr_lock(msr);
                   1562:        vm_object_unlock(object);
                   1563:        msr->flag = VM_MSYNC_DONE;
                   1564:        msr_unlock(msr);
                   1565:        thread_wakeup((event_t) msr);
                   1566:        vm_object_deallocate(object);
                   1567: 
                   1568:        return KERN_SUCCESS;
                   1569: }/* memory_object_synchronize_completed */
                   1570:          
                   1571: kern_return_t
                   1572: memory_object_set_attributes_common(
                   1573:        vm_object_t     object,
                   1574:        boolean_t       may_cache,
                   1575:        memory_object_copy_strategy_t copy_strategy,
                   1576:        boolean_t       temporary,
                   1577:        vm_size_t       cluster_size,
                   1578:         boolean_t      silent_overwrite,
                   1579:        boolean_t       advisory_pageout)
                   1580: {
                   1581:        boolean_t       object_became_ready;
                   1582: 
                   1583:         XPR(XPR_MEMORY_OBJECT,
                   1584:            "m_o_set_attr_com, object 0x%X flg %x strat %d\n",
                   1585:            (integer_t)object, (may_cache&1)|((temporary&1)<1), copy_strategy, 0, 0);
                   1586: 
                   1587:        if (object == VM_OBJECT_NULL)
                   1588:                return(KERN_INVALID_ARGUMENT);
                   1589: 
                   1590:        /*
                   1591:         *      Verify the attributes of importance
                   1592:         */
                   1593: 
                   1594:        switch(copy_strategy) {
                   1595:                case MEMORY_OBJECT_COPY_NONE:
                   1596:                case MEMORY_OBJECT_COPY_DELAY:
                   1597:                        break;
                   1598:                default:
                   1599:                        vm_object_deallocate(object);
                   1600:                        return(KERN_INVALID_ARGUMENT);
                   1601:        }
                   1602: 
                   1603: #if    !ADVISORY_PAGEOUT
                   1604:        if (silent_overwrite || advisory_pageout) {
                   1605:                vm_object_deallocate(object);
                   1606:                return(KERN_INVALID_ARGUMENT);
                   1607:        }
                   1608: #endif /* !ADVISORY_PAGEOUT */
                   1609:        if (may_cache)
                   1610:                may_cache = TRUE;
                   1611:        if (temporary)
                   1612:                temporary = TRUE;
                   1613:        if (cluster_size != 0) {
                   1614:                int     pages_per_cluster;
                   1615:                pages_per_cluster = atop(cluster_size);
                   1616:                /*
                   1617:                 * Cluster size must be integral multiple of page size,
                   1618:                 * and be a power of 2 number of pages.
                   1619:                 */
                   1620:                if ((cluster_size & (PAGE_SIZE-1)) ||
                   1621:                    ((pages_per_cluster-1) & pages_per_cluster)) {
                   1622:                        vm_object_deallocate(object);
                   1623:                        return KERN_INVALID_ARGUMENT;
                   1624:                }
                   1625:        }
                   1626: 
                   1627:        vm_object_lock(object);
                   1628: 
                   1629:        /*
                   1630:         *      Copy the attributes
                   1631:         */
                   1632:        assert(!object->internal);
                   1633:        object_became_ready = !object->pager_ready;
                   1634:        object->copy_strategy = copy_strategy;
                   1635:        object->can_persist = may_cache;
                   1636:        object->temporary = temporary;
                   1637:        object->silent_overwrite = silent_overwrite;
                   1638:        object->advisory_pageout = advisory_pageout;
                   1639:        if (cluster_size == 0)
                   1640:                cluster_size = PAGE_SIZE;
                   1641:        object->cluster_size = cluster_size;
                   1642: 
                   1643:        assert(cluster_size >= PAGE_SIZE &&
                   1644:               cluster_size % PAGE_SIZE == 0);
                   1645: 
                   1646:        /*
                   1647:         *      Wake up anyone waiting for the ready attribute
                   1648:         *      to become asserted.
                   1649:         */
                   1650: 
                   1651:        if (object_became_ready) {
                   1652:                object->pager_ready = TRUE;
                   1653:                vm_object_wakeup(object, VM_OBJECT_EVENT_PAGER_READY);
                   1654:        }
                   1655: 
                   1656:        vm_object_unlock(object);
                   1657: 
                   1658:        vm_object_deallocate(object);
                   1659: 
                   1660:        return(KERN_SUCCESS);
                   1661: }
                   1662: 
                   1663: /*
                   1664:  *     Set the memory object attribute as provided.
                   1665:  *
                   1666:  *     XXX This routine cannot be completed until the vm_msync, clean 
                   1667:  *          in place, and cluster work is completed. See ifdef notyet
                   1668:  *          below and note that memory_object_set_attributes_common()
                   1669:  *          may have to be expanded.
                   1670:  */
                   1671: kern_return_t
                   1672: memory_object_change_attributes(
                   1673:         vm_object_t             object,
                   1674:         memory_object_flavor_t  flavor,
                   1675:        memory_object_info_t    attributes,
                   1676:        mach_msg_type_number_t  count,
                   1677:         ipc_port_t              reply_to,
                   1678:         mach_msg_type_name_t    reply_to_type)
                   1679: {
                   1680:         kern_return_t                  result = KERN_SUCCESS;
                   1681:         boolean_t                      temporary;
                   1682:         boolean_t                      may_cache;
                   1683:         boolean_t                      invalidate;
                   1684:        vm_size_t                       cluster_size;
                   1685:        memory_object_copy_strategy_t   copy_strategy;
                   1686:         boolean_t                      silent_overwrite;
                   1687:        boolean_t                       advisory_pageout;
                   1688: 
                   1689:        if (object == VM_OBJECT_NULL)
                   1690:                return(KERN_INVALID_ARGUMENT);
                   1691: 
                   1692:        vm_object_lock(object);
                   1693:        temporary = object->temporary;
                   1694:        may_cache = object->can_persist;
                   1695:        copy_strategy = object->copy_strategy;
                   1696:        silent_overwrite = object->silent_overwrite;
                   1697:        advisory_pageout = object->advisory_pageout;
                   1698: #if notyet
                   1699:        invalidate = object->invalidate;
                   1700: #endif
                   1701:        cluster_size = object->cluster_size;
                   1702:        vm_object_unlock(object);       
                   1703: 
                   1704:        switch (flavor) {
                   1705:            case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
                   1706:            {
                   1707:                 old_memory_object_behave_info_t     behave;
                   1708: 
                   1709:                 if (count != OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
                   1710:                         result = KERN_INVALID_ARGUMENT;
                   1711:                         break;
                   1712:                 }
                   1713: 
                   1714:                 behave = (old_memory_object_behave_info_t) attributes;
                   1715: 
                   1716:                temporary = behave->temporary;
                   1717:                invalidate = behave->invalidate;
                   1718:                copy_strategy = behave->copy_strategy;
                   1719: 
                   1720:                break;
                   1721:            }
                   1722: 
                   1723:            case MEMORY_OBJECT_BEHAVIOR_INFO:
                   1724:            {
                   1725:                 memory_object_behave_info_t     behave;
                   1726: 
                   1727:                 if (count != MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
                   1728:                         result = KERN_INVALID_ARGUMENT;
                   1729:                         break;
                   1730:                 }
                   1731: 
                   1732:                 behave = (memory_object_behave_info_t) attributes;
                   1733: 
                   1734:                temporary = behave->temporary;
                   1735:                invalidate = behave->invalidate;
                   1736:                copy_strategy = behave->copy_strategy;
                   1737:                silent_overwrite = behave->silent_overwrite;
                   1738:                advisory_pageout = behave->advisory_pageout;
                   1739:                break;
                   1740:            }
                   1741: 
                   1742:            case MEMORY_OBJECT_PERFORMANCE_INFO:
                   1743:            {
                   1744:                memory_object_perf_info_t       perf;
                   1745: 
                   1746:                 if (count != MEMORY_OBJECT_PERF_INFO_COUNT) {
                   1747:                         result = KERN_INVALID_ARGUMENT;
                   1748:                         break;
                   1749:                 }
                   1750: 
                   1751:                 perf = (memory_object_perf_info_t) attributes;
                   1752: 
                   1753:                may_cache = perf->may_cache;
                   1754:                cluster_size = round_page(perf->cluster_size);
                   1755: 
                   1756:                break;
                   1757:            }
                   1758: 
                   1759:            case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
                   1760:            {
                   1761:                old_memory_object_attr_info_t   attr;
                   1762: 
                   1763:                 if (count != OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
                   1764:                         result = KERN_INVALID_ARGUMENT;
                   1765:                         break;
                   1766:                 }
                   1767: 
                   1768:                attr = (old_memory_object_attr_info_t) attributes;
                   1769: 
                   1770:                 may_cache = attr->may_cache;
                   1771:                 copy_strategy = attr->copy_strategy;
                   1772:                cluster_size = page_size;
                   1773: 
                   1774:                break;
                   1775:            }
                   1776: 
                   1777:            case MEMORY_OBJECT_ATTRIBUTE_INFO:
                   1778:            {
                   1779:                memory_object_attr_info_t       attr;
                   1780: 
                   1781:                 if (count != MEMORY_OBJECT_ATTR_INFO_COUNT) {
                   1782:                         result = KERN_INVALID_ARGUMENT;
                   1783:                         break;
                   1784:                 }
                   1785: 
                   1786:                attr = (memory_object_attr_info_t) attributes;
                   1787: 
                   1788:                copy_strategy = attr->copy_strategy;
                   1789:                 may_cache = attr->may_cache_object;
                   1790:                cluster_size = attr->cluster_size;
                   1791:                temporary = attr->temporary;
                   1792: 
                   1793:                break;
                   1794:            }
                   1795: 
                   1796:            default:
                   1797:                result = KERN_INVALID_ARGUMENT;
                   1798:                break;
                   1799:        }
                   1800: 
                   1801:        if (result != KERN_SUCCESS) {
                   1802:                vm_object_deallocate(object);
                   1803:                return(result);
                   1804:        }
                   1805: 
                   1806:        if (copy_strategy == MEMORY_OBJECT_COPY_TEMPORARY) {
                   1807:                copy_strategy = MEMORY_OBJECT_COPY_DELAY;
                   1808:                temporary = TRUE;
                   1809:        } else {
                   1810:                temporary = FALSE;
                   1811:        }
                   1812: 
                   1813:        /*
                   1814:         *      Do the work and throw away our object reference.  It
                   1815:         *      is important that the object reference be deallocated
                   1816:         *      BEFORE sending the reply.  The whole point of the reply
                   1817:         *      is that it shows up after the terminate message that
                   1818:         *      may be generated by setting the object uncacheable.
                   1819:         *
                   1820:         * XXX  may_cache may become a tri-valued variable to handle
                   1821:         * XXX  uncache if not in use.
                   1822:         */
                   1823:        result = memory_object_set_attributes_common(object,
                   1824:                                                     may_cache,
                   1825:                                                     copy_strategy,
                   1826:                                                     temporary,
                   1827:                                                     cluster_size,
                   1828:                                                     silent_overwrite,
                   1829:                                                     advisory_pageout);
                   1830: 
                   1831:         if (IP_VALID(reply_to)) {
                   1832:                 /* consumes our naked send-once/send right for reply_to */
                   1833:                 (void) memory_object_change_completed(reply_to, reply_to_type,
                   1834:                       object->alive ?
                   1835:                                 object->pager_request : PAGER_REQUEST_NULL,
                   1836:                       flavor);
                   1837:        }
                   1838: 
                   1839:        return(result);
                   1840: }
                   1841: 
                   1842: kern_return_t
                   1843: memory_object_get_attributes(
                   1844:         vm_object_t            object,
                   1845:         memory_object_flavor_t         flavor,
                   1846:        memory_object_info_t    attributes,     /* pointer to OUT array */
                   1847:        mach_msg_type_number_t  *count)         /* IN/OUT */
                   1848: {
                   1849:        kern_return_t ret = KERN_SUCCESS;
                   1850: 
                   1851:         if (object == VM_OBJECT_NULL)
                   1852:                 return(KERN_INVALID_ARGUMENT);
                   1853: 
                   1854:         vm_object_lock(object);
                   1855: 
                   1856:        switch (flavor) {
                   1857:            case OLD_MEMORY_OBJECT_BEHAVIOR_INFO:
                   1858:            {
                   1859:                old_memory_object_behave_info_t behave;
                   1860: 
                   1861:                if (*count < OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
                   1862:                        ret = KERN_INVALID_ARGUMENT;
                   1863:                        break;
                   1864:                }
                   1865: 
                   1866:                behave = (old_memory_object_behave_info_t) attributes;
                   1867:                behave->copy_strategy = object->copy_strategy;
                   1868:                behave->temporary = object->temporary;
                   1869: #if notyet     /* remove when vm_msync complies and clean in place fini */
                   1870:                 behave->invalidate = object->invalidate;
                   1871: #else
                   1872:                behave->invalidate = FALSE;
                   1873: #endif
                   1874: 
                   1875:                *count = OLD_MEMORY_OBJECT_BEHAVE_INFO_COUNT;
                   1876:                break;
                   1877:            }
                   1878: 
                   1879:            case MEMORY_OBJECT_BEHAVIOR_INFO:
                   1880:            {
                   1881:                memory_object_behave_info_t     behave;
                   1882: 
                   1883:                if (*count < MEMORY_OBJECT_BEHAVE_INFO_COUNT) {
                   1884:                         ret = KERN_INVALID_ARGUMENT;
                   1885:                         break;
                   1886:                 }
                   1887: 
                   1888:                 behave = (memory_object_behave_info_t) attributes;
                   1889:                 behave->copy_strategy = object->copy_strategy;
                   1890:                behave->temporary = object->temporary;
                   1891: #if notyet     /* remove when vm_msync complies and clean in place fini */
                   1892:                 behave->invalidate = object->invalidate;
                   1893: #else
                   1894:                behave->invalidate = FALSE;
                   1895: #endif
                   1896:                behave->advisory_pageout = object->advisory_pageout;
                   1897:                behave->silent_overwrite = object->silent_overwrite;
                   1898:                 *count = MEMORY_OBJECT_BEHAVE_INFO_COUNT;
                   1899:                break;
                   1900:            }
                   1901: 
                   1902:            case MEMORY_OBJECT_PERFORMANCE_INFO:
                   1903:            {
                   1904:                memory_object_perf_info_t       perf;
                   1905: 
                   1906:                if (*count < MEMORY_OBJECT_PERF_INFO_COUNT) {
                   1907:                        ret = KERN_INVALID_ARGUMENT;
                   1908:                        break;
                   1909:                }
                   1910: 
                   1911:                perf = (memory_object_perf_info_t) attributes;
                   1912:                perf->cluster_size = object->cluster_size;
                   1913:                perf->may_cache = object->can_persist;
                   1914: 
                   1915:                *count = MEMORY_OBJECT_PERF_INFO_COUNT;
                   1916:                break;
                   1917:            }
                   1918: 
                   1919:             case OLD_MEMORY_OBJECT_ATTRIBUTE_INFO:
                   1920:             {
                   1921:                 old_memory_object_attr_info_t       attr;
                   1922: 
                   1923:                 if (*count < OLD_MEMORY_OBJECT_ATTR_INFO_COUNT) {
                   1924:                         ret = KERN_INVALID_ARGUMENT;
                   1925:                         break;
                   1926:                 }
                   1927: 
                   1928:                 attr = (old_memory_object_attr_info_t) attributes;
                   1929:                attr->may_cache = object->can_persist;
                   1930:                attr->copy_strategy = object->copy_strategy;
                   1931: 
                   1932:                 *count = OLD_MEMORY_OBJECT_ATTR_INFO_COUNT;
                   1933:                 break;
                   1934:             }
                   1935: 
                   1936:             case MEMORY_OBJECT_ATTRIBUTE_INFO:
                   1937:             {
                   1938:                 memory_object_attr_info_t       attr;
                   1939: 
                   1940:                 if (*count < MEMORY_OBJECT_ATTR_INFO_COUNT) {
                   1941:                         ret = KERN_INVALID_ARGUMENT;
                   1942:                         break;
                   1943:                 }
                   1944: 
                   1945:                 attr = (memory_object_attr_info_t) attributes;
                   1946:                attr->copy_strategy = object->copy_strategy;
                   1947:                attr->cluster_size = object->cluster_size;
                   1948:                attr->may_cache_object = object->can_persist;
                   1949:                attr->temporary = object->temporary;
                   1950: 
                   1951:                 *count = MEMORY_OBJECT_ATTR_INFO_COUNT;
                   1952:                 break;
                   1953:             }
                   1954: 
                   1955:            default:
                   1956:                ret = KERN_INVALID_ARGUMENT;
                   1957:                break;
                   1958:        }
                   1959: 
                   1960:         vm_object_unlock(object);
                   1961: 
                   1962:         vm_object_deallocate(object);
                   1963: 
                   1964:         return(ret);
                   1965: }
                   1966: 
                   1967: int vm_stat_discard_cleared_reply = 0;
                   1968: int vm_stat_discard_cleared_unset = 0;
                   1969: int vm_stat_discard_cleared_too_late = 0;
                   1970: 
                   1971: #if    ADVISORY_PAGEOUT
                   1972: kern_return_t
                   1973: memory_object_discard_reply(
                   1974:        vm_object_t             object,
                   1975:        vm_offset_t             requested_offset,
                   1976:        vm_size_t               requested_size,
                   1977:        vm_offset_t             discard_offset,
                   1978:        vm_size_t               discard_size,
                   1979:        memory_object_return_t  should_return,
                   1980:        ipc_port_t              reply_to,
                   1981:        mach_msg_type_name_t    reply_to_type)
                   1982: {
                   1983:        vm_offset_t     original_offset = discard_offset;
                   1984:        vm_size_t       original_size = discard_size;
                   1985: 
                   1986:        XPR(XPR_MEMORY_OBJECT,
                   1987:            "m_o_discard_reply, obj 0x%X req_off 0x%X req_size 0x%X "
                   1988:            "discard_off 0x%X discard_size 0x%X\n",
                   1989:            (integer_t) object, requested_offset, requested_size,
                   1990:            discard_offset, discard_size);
                   1991: 
                   1992:        /*
                   1993:         *      Check for bogus arguments.
                   1994:         */
                   1995:        if (object == VM_OBJECT_NULL)
                   1996:                return KERN_INVALID_ARGUMENT;
                   1997: 
                   1998:        requested_size = round_page(requested_size);
                   1999:        discard_size = round_page(discard_size);
                   2000: 
                   2001:        /*
                   2002:         *      Lock the object, and acquire a paging reference to
                   2003:         *      prevent the memory_object and control ports from
                   2004:         *      being destroyed.
                   2005:         */
                   2006: 
                   2007:        vm_object_lock(object);
                   2008:        vm_object_paging_begin(object);
                   2009:        discard_offset -= object->paging_offset;
                   2010:        requested_offset -= object->paging_offset;
                   2011: 
                   2012:        if (discard_size != 0) {
                   2013:                (void) memory_object_update(object,
                   2014:                                            discard_offset, discard_size,
                   2015:                                            should_return, TRUE, VM_PROT_ALL);
                   2016:        }
                   2017: 
                   2018:        if (original_offset != requested_offset ||
                   2019:            discard_size != requested_size) {
                   2020:                /*
                   2021:                 * We're not discarding the requested pages, so reset 
                   2022:                 * the "discard_request" flag on the requested pages.
                   2023:                 * But don't rehabilitate more pages than we discard.
                   2024:                 */
                   2025:                while (requested_size != 0) {
                   2026:                        vm_page_t m;
                   2027: 
                   2028:                        m = vm_page_lookup(object, requested_offset);
                   2029:                        if (m != VM_PAGE_NULL) {
                   2030:                                if (discard_size != 0) {
                   2031:                                        if (m->discard_request) {
                   2032:                                                m->discard_request = FALSE;
                   2033:                                                vm_stat_discard_cleared_reply++;
                   2034:                                        } else {
                   2035:                                                vm_stat_discard_cleared_unset++;
                   2036:                                        }
                   2037:                                }
                   2038:                        } else {
                   2039:                                vm_stat_discard_cleared_too_late++;
                   2040:                        }
                   2041: 
                   2042:                        requested_offset += PAGE_SIZE;
                   2043:                        requested_size -= PAGE_SIZE;
                   2044:                        discard_size -= PAGE_SIZE;
                   2045:                }
                   2046:        }
                   2047: 
                   2048:        if (IP_VALID(reply_to)) {
                   2049:                vm_object_unlock(object);
                   2050: 
                   2051:                /* consumes our naked send-once/send right for reply_to */
                   2052:                (void) memory_object_lock_completed(reply_to, reply_to_type,
                   2053:                                                    object->pager_request,
                   2054:                                                    original_offset,
                   2055:                                                    original_size);
                   2056: 
                   2057:                vm_object_lock(object);
                   2058:        }
                   2059: 
                   2060:        vm_object_paging_end(object);
                   2061:        vm_object_unlock(object);
                   2062:        vm_object_deallocate(object);
                   2063: 
                   2064:        return KERN_SUCCESS;
                   2065: }
                   2066: #endif /* ADVISORY_PAGEOUT */
                   2067: 
                   2068: /*
                   2069:  * vm_set_default_memory_manager(): 
                   2070:  *     [Obsolete]
                   2071:  */
                   2072: kern_return_t
                   2073: vm_set_default_memory_manager(
                   2074:        host_t          host,
                   2075:        ipc_port_t      *default_manager)
                   2076: {
                   2077:        return(host_default_memory_manager(host, default_manager, 4*PAGE_SIZE));
                   2078: }
                   2079: 
                   2080: /*
                   2081:  *     Routine:        host_default_memory_manager
                   2082:  *     Purpose:
                   2083:  *             set/get the default memory manager port and default cluster
                   2084:  *             size.
                   2085:  *
                   2086:  *             If successful, consumes the supplied naked send right.
                   2087:  */
                   2088: kern_return_t
                   2089: host_default_memory_manager(
                   2090:        host_t          host,
                   2091:        ipc_port_t      *default_manager,
                   2092:        vm_size_t       cluster_size)
                   2093: {
                   2094:        ipc_port_t current_manager;
                   2095:        ipc_port_t new_manager;
                   2096:        ipc_port_t returned_manager;
                   2097: 
                   2098:        if (host == HOST_NULL)
                   2099:                return(KERN_INVALID_HOST);
                   2100: 
                   2101:        new_manager = *default_manager;
                   2102:        mutex_lock(&memory_manager_default_lock);
                   2103:        current_manager = memory_manager_default;
                   2104: 
                   2105:        if (new_manager == IP_NULL) {
                   2106:                /*
                   2107:                 *      Retrieve the current value.
                   2108:                 */
                   2109: 
                   2110:                returned_manager = ipc_port_copy_send(current_manager);
                   2111:        } else {
                   2112:                /*
                   2113:                 *      Retrieve the current value,
                   2114:                 *      and replace it with the supplied value.
                   2115:                 *      We consume the supplied naked send right.
                   2116:                 */
                   2117: 
                   2118:                returned_manager = current_manager;
                   2119:                memory_manager_default = new_manager;
                   2120:                if (cluster_size % PAGE_SIZE != 0) {
                   2121: #if 0
                   2122:                        mutex_unlock(&memory_manager_default_lock);
                   2123:                        return KERN_INVALID_ARGUMENT;
                   2124: #else
                   2125:                        cluster_size = round_page(cluster_size);
                   2126: #endif
                   2127:                }
                   2128:                memory_manager_default_cluster = cluster_size;
                   2129: 
                   2130:                /*
                   2131:                 *      In case anyone's been waiting for a memory
                   2132:                 *      manager to be established, wake them up.
                   2133:                 */
                   2134: 
                   2135:                thread_wakeup((event_t) &memory_manager_default);
                   2136:        }
                   2137: 
                   2138:        mutex_unlock(&memory_manager_default_lock);
                   2139: 
                   2140:        *default_manager = returned_manager;
                   2141:        return(KERN_SUCCESS);
                   2142: }
                   2143: 
                   2144: /*
                   2145:  *     Routine:        memory_manager_default_reference
                   2146:  *     Purpose:
                   2147:  *             Returns a naked send right for the default
                   2148:  *             memory manager.  The returned right is always
                   2149:  *             valid (not IP_NULL or IP_DEAD).
                   2150:  */
                   2151: 
                   2152: ipc_port_t
                   2153: memory_manager_default_reference(
                   2154:        vm_size_t       *cluster_size)
                   2155: {
                   2156:        ipc_port_t current_manager;
                   2157: 
                   2158:        mutex_lock(&memory_manager_default_lock);
                   2159: 
                   2160:        while (current_manager = ipc_port_copy_send(memory_manager_default),
                   2161:               !IP_VALID(current_manager)) {
                   2162:                thread_sleep_mutex((event_t) &memory_manager_default,
                   2163:                        &memory_manager_default_lock, THREAD_UNINT);
                   2164:                mutex_lock(&memory_manager_default_lock);
                   2165:        }
                   2166:        *cluster_size = memory_manager_default_cluster;
                   2167: 
                   2168:        mutex_unlock(&memory_manager_default_lock);
                   2169: 
                   2170:        return current_manager;
                   2171: }
                   2172: 
                   2173: /*
                   2174:  *     Routine:        memory_manager_default_port
                   2175:  *     Purpose:
                   2176:  *             Returns true if the receiver for the port
                   2177:  *             is the default memory manager.
                   2178:  *
                   2179:  *             This is a hack to let ds_read_done
                   2180:  *             know when it should keep memory wired.
                   2181:  */
                   2182: 
                   2183: boolean_t
                   2184: memory_manager_default_port(
                   2185:        ipc_port_t port)
                   2186: {
                   2187:        ipc_port_t current;
                   2188:        boolean_t result;
                   2189: 
                   2190:        mutex_lock(&memory_manager_default_lock);
                   2191:        current = memory_manager_default;
                   2192:        if (IP_VALID(current)) {
                   2193:                /*
                   2194:                 *      There is no point in bothering to lock
                   2195:                 *      both ports, which would be painful to do.
                   2196:                 *      If the receive rights are moving around,
                   2197:                 *      we might be inaccurate.
                   2198:                 */
                   2199: 
                   2200:                result = port->ip_receiver == current->ip_receiver;
                   2201:        } else
                   2202:                result = FALSE;
                   2203:        mutex_unlock(&memory_manager_default_lock);
                   2204: 
                   2205:        return result;
                   2206: }
                   2207: 
                   2208: /*
                   2209:  *     Routine:        memory_manager_default_check
                   2210:  *
                   2211:  *     Purpose:
                   2212:  *             Check whether a default memory manager has been set
                   2213:  *             up yet, or not. Returns KERN_SUCCESS if dmm exists,
                   2214:  *             and KERN_FAILURE if dmm does not exist.
                   2215:  *
                   2216:  *             If there is no default memory manager, log an error,
                   2217:  *             but only the first time.
                   2218:  *
                   2219:  */
                   2220: kern_return_t
                   2221: memory_manager_default_check(void)
                   2222: {
                   2223:        ipc_port_t current;
                   2224: 
                   2225:        mutex_lock(&memory_manager_default_lock);
                   2226:        current = memory_manager_default;
                   2227:        if (!IP_VALID(current)) {
                   2228:                static boolean_t logged;        /* initialized to 0 */
                   2229:                boolean_t       complain = !logged;
                   2230:                logged = TRUE;
                   2231:                mutex_unlock(&memory_manager_default_lock);
                   2232:                if (complain)
                   2233:                        printf("Warning: No default memory manager\n");
                   2234:                return(KERN_FAILURE);
                   2235:        } else {
                   2236:                mutex_unlock(&memory_manager_default_lock);
                   2237:                return(KERN_SUCCESS);
                   2238:        }
                   2239: }
                   2240: 
                   2241: void
                   2242: memory_manager_default_init(void)
                   2243: {
                   2244:        memory_manager_default = IP_NULL;
                   2245:        mutex_init(&memory_manager_default_lock, ETAP_VM_MEMMAN);
                   2246: }
                   2247: 
                   2248: 
                   2249: void
                   2250: memory_object_kill_pages(
                   2251:        vm_object_t     object,
                   2252:        vm_offset_t     offset,
                   2253:        vm_size_t       size)
                   2254: {
                   2255:        register vm_page_t      m;
                   2256: 
                   2257:        /*
                   2258:         * entered with object lock held, acquire a paging reference to
                   2259:         * prevent the memory_object and control ports from
                   2260:         * being destroyed.
                   2261:         */
                   2262:        vm_object_paging_begin(object);
                   2263: 
                   2264:        for (;
                   2265:             size != 0;
                   2266:             size -= PAGE_SIZE, offset += PAGE_SIZE)
                   2267:        {
                   2268:                if ((m = vm_page_lookup(object, offset)) != VM_PAGE_NULL) {
                   2269:                        if (memory_object_lock_page(m, MEMORY_OBJECT_RETURN_NONE, TRUE, VM_PROT_NO_CHANGE) ==
                   2270:                            MEMORY_OBJECT_LOCK_RESULT_DONE)
                   2271:                                vm_external_state_clr(object->existence_map, offset);
                   2272:                }
                   2273:        }
                   2274:        vm_object_paging_end(object);
                   2275: }

unix.superglobalmegacorp.com

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