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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* 
                     26:  * 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.