Annotation of kernel/vm/vm_synchronize.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* 
        !            26:  * Copyright (c) 1990 NeXT, Inc.
        !            27:  *
        !            28:  *  History:
        !            29:  *
        !            30:  *     6-Aug-90: Brian Pinkerton at NeXT
        !            31:  *             created
        !            32:  */
        !            33:  
        !            34: 
        !            35: #import <mach_xp.h>
        !            36: 
        !            37: #import <sys/types.h>
        !            38: #import <sys/param.h>
        !            39: 
        !            40: #import <mach/vm_param.h>
        !            41: #import <vm/vm_object.h>
        !            42: #import <vm/vm_map.h>
        !            43: #import <vm/vm_page.h>
        !            44: #import <mach/vm_statistics.h>
        !            45: 
        !            46: #import <mach/boolean.h>
        !            47: #import <mach/kern_return.h>
        !            48: #import <kern/task.h>
        !            49: #import <kern/kalloc.h>
        !            50: 
        !            51: #import <mach/mach_types.h>    /* to get vm_address_t */
        !            52: 
        !            53: 
        !            54: static kern_return_t map_push_range(vm_map_t map, vm_offset_t start, vm_offset_t end);
        !            55:        
        !            56: static kern_return_t object_push(vm_object_t object, vm_offset_t object_start, vm_offset_t object_end);
        !            57:        
        !            58: enum pageout_outcome { PAGEOUT_SUCCESS, PAGEOUT_ERROR, PAGEOUT_RERUN };
        !            59: 
        !            60: /*
        !            61:  * Push all pages to disk.
        !            62:  */
        !            63: kern_return_t
        !            64: vm_synchronize(
        !            65:        vm_map_t        task_map,
        !            66:        vm_address_t    vmaddr,
        !            67:        vm_size_t       vmsize)
        !            68: {
        !            69:        kern_return_t   result;
        !            70: 
        !            71:        if (!task_map)
        !            72:                return KERN_FAILURE;
        !            73: 
        !            74:        if (vmsize == 0)
        !            75:                vmsize = task_map->max_offset - task_map->min_offset;
        !            76: 
        !            77:        if (vmaddr == 0)
        !            78:                vmaddr = task_map->min_offset;
        !            79: 
        !            80:        result = map_push_range(task_map, vmaddr, vmaddr+vmsize);
        !            81:        
        !            82:        return result;
        !            83: }
        !            84: 
        !            85: 
        !            86: /*
        !            87:  * Push a range of pages in a map.
        !            88:  */
        !            89: static kern_return_t
        !            90: map_push_range(
        !            91:        vm_map_t        map,
        !            92:        vm_offset_t     start,
        !            93:        vm_offset_t     end)
        !            94: {
        !            95:        vm_map_entry_t  entry;
        !            96:        vm_object_t     object;
        !            97:        vm_offset_t     tend;
        !            98:        int             offset;
        !            99:        kern_return_t   rtn, realRtn = KERN_SUCCESS;
        !           100: 
        !           101:        vm_map_lock_read(map);
        !           102:        /*
        !           103:         * Push all the pages in this map.
        !           104:         */
        !           105:        for (  entry = vm_map_first_entry(map)
        !           106:             ; entry != vm_map_to_entry(map)
        !           107:             ; entry = entry->vme_next)
        !           108:        {
        !           109:                if (entry->is_a_map || entry->is_sub_map) {
        !           110:                        vm_map_t sub_map;
        !           111:                        /*
        !           112:                         * Recurse over this sub-map.
        !           113:                         */
        !           114:                        sub_map = entry->object.sub_map;
        !           115:                        rtn = map_push_range(sub_map, start, end);
        !           116:                        if (rtn == KERN_FAILURE)
        !           117:                                realRtn = KERN_FAILURE;
        !           118:                        continue;
        !           119:                }
        !           120:                if (entry->vme_start > end || entry->vme_end <= start)
        !           121:                        continue;
        !           122: 
        !           123:                /*
        !           124:                 * Push the pages we can see in this object chain.
        !           125:                 */
        !           126:                object = entry->object.vm_object;
        !           127:                if (entry->vme_start > start)
        !           128:                        start = entry->vme_start;
        !           129:                tend = (entry->vme_end > end) ? end : entry->vme_end;
        !           130:                offset = entry->offset + start - entry->vme_start;
        !           131:                rtn = object_push(object, offset, offset + tend - start);
        !           132:                if (rtn)
        !           133:                        realRtn = KERN_FAILURE;
        !           134:        }
        !           135:        vm_map_unlock(map);
        !           136: 
        !           137:        return realRtn;
        !           138: }
        !           139: 
        !           140: 
        !           141: /*
        !           142:  *  Page out a page belonging to the given object.  The object must be locked.
        !           143:  */
        !           144: static enum pageout_outcome
        !           145: vm_pageout_page(vm_object_t object, vm_page_t m)
        !           146: {
        !           147:        enum pageout_outcome pageout_succeeded;
        !           148:        vm_pager_t pager = object->pager;
        !           149:        
        !           150:        vm_page_lock_queues();
        !           151:        if (m->clean && !pmap_is_modified(VM_PAGE_TO_PHYS(m))) {
        !           152:                vm_page_unlock_queues();
        !           153:                return PAGEOUT_SUCCESS;
        !           154:        }
        !           155: 
        !           156:        /*
        !           157:         *  If the page is already busy, sleep on it...
        !           158:         */
        !           159:        while (m->busy) {
        !           160:                vm_page_unlock_queues();
        !           161:                PAGE_ASSERT_WAIT(m, FALSE);
        !           162:                vm_object_unlock(object);
        !           163:                thread_block();
        !           164:                vm_object_lock(object);
        !           165:                return PAGEOUT_RERUN;
        !           166:        }
        !           167:        
        !           168:        object->paging_in_progress++;
        !           169:        
        !           170:        m->busy = TRUE;
        !           171:        if (m->inactive)
        !           172:                vm_page_activate(m);
        !           173:        vm_page_deactivate(m);
        !           174:        
        !           175:        pmap_remove_all(VM_PAGE_TO_PHYS(m));
        !           176:        vm_stat.pageouts++;
        !           177: 
        !           178:        vm_page_unlock_queues();
        !           179:        if (pager == vm_pager_null) {
        !           180:                object->paging_in_progress--;
        !           181:                return PAGEOUT_ERROR;
        !           182:        }
        !           183:        vm_object_unlock(object);
        !           184:        
        !           185:        pageout_succeeded = PAGEOUT_ERROR;
        !           186:        if (pager != vm_pager_null) {
        !           187:                if (vm_pager_put(pager, m) == PAGER_SUCCESS) {
        !           188:                        pageout_succeeded = PAGEOUT_SUCCESS;
        !           189:                }
        !           190:        }
        !           191: 
        !           192:        vm_object_lock(object);
        !           193:        vm_page_lock_queues();
        !           194:        m->busy = FALSE;
        !           195:        PAGE_WAKEUP(m);
        !           196:        
        !           197:        object->paging_in_progress--;
        !           198:        vm_page_unlock_queues();
        !           199:        
        !           200:        return pageout_succeeded;
        !           201: }
        !           202: 
        !           203: 
        !           204: /*
        !           205:  *  Count resident pages in this object and all shadow objects over the
        !           206:  *  specified address range.
        !           207:  *
        !           208:  *  If we encounter an error, we'll attempt to push the rest of the pages,
        !           209:  *  and return an error for the whole object.
        !           210:  *
        !           211:  *  If we encounter a locked page, then we'll restart
        !           212:  */
        !           213: static kern_return_t
        !           214: object_push(vm_object_t object, vm_offset_t object_start, vm_offset_t object_end)
        !           215: {
        !           216:        vm_object_t     shadow;
        !           217:        vm_page_t       page;
        !           218:        vm_size_t       object_size;
        !           219:        int             flags;
        !           220:        int             allPageoutsSucceeded = TRUE;
        !           221:        kern_return_t   rtn = FALSE;
        !           222: 
        !           223:        if (object == VM_OBJECT_NULL)
        !           224:                return KERN_SUCCESS;
        !           225: 
        !           226:        vm_object_lock(object);
        !           227: 
        !           228: retry:
        !           229:        for (  page = (vm_page_t) queue_first(&object->memq)
        !           230:             ; !queue_end(&object->memq, (queue_entry_t) page)
        !           231:             ; page = (vm_page_t) queue_next(&page->listq))
        !           232:        {
        !           233:                /*
        !           234:                 * If this page isn't actually referenced from this
        !           235:                 * entry, then forget it.
        !           236:                 */
        !           237:                if (page->offset < object_start || page->offset >= object_end)
        !           238:                        continue;
        !           239: 
        !           240:                /*
        !           241:                 *  Push this page.  If we fail, retry on the whole object.
        !           242:                 */
        !           243:                switch (vm_pageout_page(object, page)) {
        !           244:                        case PAGEOUT_RERUN:
        !           245:                                goto retry;
        !           246:                        case PAGEOUT_ERROR:
        !           247:                                allPageoutsSucceeded = FALSE;
        !           248:                        case PAGEOUT_SUCCESS:
        !           249:                        default:
        !           250:                                break;
        !           251:                }
        !           252:        }
        !           253: 
        !           254:        /*
        !           255:         * Recurse over shadow objects.
        !           256:         */
        !           257:        object_size = object_end - object_start;
        !           258:        if (object->size && object_end - object_start > object->size)
        !           259:                object_size = object->size;
        !           260:        object_start += object->shadow_offset;
        !           261:        object_end = object_start + object_size;
        !           262: 
        !           263:        if (object_push(object->shadow, object_start, object_end) != KERN_SUCCESS)
        !           264:                rtn = KERN_FAILURE;
        !           265:        
        !           266:        vm_object_unlock(object);
        !           267:        thread_wakeup(object);
        !           268:        
        !           269:        if (rtn == KERN_FAILURE || !allPageoutsSucceeded)
        !           270:                return KERN_FAILURE;
        !           271:        else
        !           272:                return KERN_SUCCESS;
        !           273: }
        !           274: 

unix.superglobalmegacorp.com

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