Annotation of kernel/vm/vm_policy.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) 1992 NeXT, Inc.
        !            27:  *
        !            28:  *  History:
        !            29:  *
        !            30:  *     14-Dec-92: Brian Pinkerton at NeXT
        !            31:  *             Created
        !            32:  */
        !            33: #import <sys/types.h>
        !            34: #import <sys/param.h>
        !            35: 
        !            36: #import <mach/mach_types.h>
        !            37: #import <mach/vm_param.h>
        !            38: #import <mach/boolean.h>
        !            39: #import <mach/kern_return.h>
        !            40: #import <mach/vm_policy.h>
        !            41: 
        !            42: #import <vm/vm_object.h>
        !            43: #import <vm/vm_map.h>
        !            44: #import <vm/vm_page.h>
        !            45: #import <vm/vnode_pager.h>
        !            46: 
        !            47: #import <kern/task.h>
        !            48: #import <kern/kalloc.h>
        !            49: 
        !            50: 
        !            51: /*
        !            52:  *     Returns the given page to the HEAD of the free list,
        !            53:  *     disassociating it with any VM object.
        !            54:  *
        !            55:  *     Object and page must be locked prior to entry.
        !            56:  */
        !            57: static void
        !            58: vm_page_free_head(mem)
        !            59:        register vm_page_t      mem;
        !            60: {
        !            61:        vm_page_remove(mem);
        !            62:        if (mem->free)
        !            63:                return;
        !            64: 
        !            65:        if (mem->active) {
        !            66:                queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq);
        !            67:                mem->active = FALSE;
        !            68:                vm_page_active_count--;
        !            69:        }
        !            70: 
        !            71:        if (mem->inactive) {
        !            72:                queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq);
        !            73:                mem->inactive = FALSE;
        !            74:                vm_page_inactive_count--;
        !            75:        }
        !            76: 
        !            77:        if (!mem->fictitious) {
        !            78:                int     spl;
        !            79: 
        !            80:                spl = splimp();
        !            81:                simple_lock(&vm_page_queue_free_lock);
        !            82:                queue_enter_first(&vm_page_queue_free, mem, vm_page_t, pageq);
        !            83:                mem->free = TRUE;
        !            84:                vm_page_free_count++;
        !            85:                simple_unlock(&vm_page_queue_free_lock);
        !            86:                splx(spl);
        !            87:        }
        !            88: }
        !            89: 
        !            90: 
        !            91: /*
        !            92:  *  Do something with a particular page.  This function is the locus for all
        !            93:  *  policy decisions.
        !            94:  */
        !            95: void
        !            96: vm_policy_apply(vm_object_t object, vm_page_t m, int when)
        !            97: {
        !            98:        boolean_t       shared = FALSE;
        !            99:        
        !           100:        /*
        !           101:         *  Determine whether an object is "shared".  It is shared if it has
        !           102:         *  more than two references, and it's backed by something that's not
        !           103:         *  the swapfile.
        !           104:         *
        !           105:         *  Note: this is a pretty bogus definition of shared.  The ref count
        !           106:         *  on the object could easily be high even if only one task has this
        !           107:         *  object mapped.  This is OK, though, because we're making a
        !           108:         *  conservative decision.  Someone can always turn on the shared
        !           109:         *  flag if they want to be really aggressive.
        !           110:         */
        !           111:        if (object->ref_count > 2) {
        !           112:                if (object->pager && !object->pager->is_device) {
        !           113:                        vnode_pager_t pager = (vnode_pager_t) object->pager;
        !           114:                        shared = !pager->vs_swapfile;
        !           115:                }
        !           116:        }
        !           117: 
        !           118:        if (!(when & VM_DEACTIVATE_SHARED) && shared)
        !           119:                return;
        !           120: 
        !           121:        vm_page_lock_queues();
        !           122: 
        !           123:        switch (when) {
        !           124:                /*
        !           125:                 *  Make this page as cold as possible.  That means that we
        !           126:                 *  try to free the page.
        !           127:                 */
        !           128:                case VM_DEACTIVATE_NOW:
        !           129:                        if (m->clean && !pmap_is_modified(VM_PAGE_TO_PHYS(m)))
        !           130:                                vm_page_free_head(m);
        !           131:                        else {
        !           132:                                if (m->active)
        !           133:                                        vm_page_deactivate(m);
        !           134:                        }
        !           135:                        pmap_remove_all(VM_PAGE_TO_PHYS(m));
        !           136:                        break;
        !           137:                
        !           138:                /*
        !           139:                 *  a little warmer.
        !           140:                 */
        !           141:                case VM_DEACTIVATE_SOON:
        !           142:                        if (m->active)
        !           143:                                vm_page_deactivate(m);
        !           144:                        break;
        !           145:                default:
        !           146:                        break;
        !           147:        }
        !           148: 
        !           149:        vm_page_unlock_queues();
        !           150: }
        !           151: 
        !           152: 
        !           153: /*
        !           154:  *  Deactivate active pages in this object and all shadow objects over the
        !           155:  *  specified address range.
        !           156:  *
        !           157:  *  If we encounter an error, we'll attempt to push the rest of the pages,
        !           158:  *  and return an error for the whole object.
        !           159:  *
        !           160:  *  If we encounter a locked page, then we'll skip it...
        !           161:  */
        !           162: static void
        !           163: deactivate_object(vm_object_t object, vm_offset_t start, vm_offset_t end, int temperature)
        !           164: {
        !           165:        vm_object_t     shadow;
        !           166:        vm_page_t       page;
        !           167:        vm_size_t       size;
        !           168:        int             flags;
        !           169: 
        !           170:        if (object == VM_OBJECT_NULL)
        !           171:                return;
        !           172: 
        !           173:        vm_object_lock(object);
        !           174: 
        !           175:        for (page = (vm_page_t) queue_first(&object->memq);
        !           176:             !queue_end(&object->memq, (queue_entry_t) page);
        !           177:             page = (vm_page_t) queue_next(&page->listq))
        !           178:        {
        !           179:                /*
        !           180:                 * If this page isn't actually referenced from this
        !           181:                 * entry, then forget it.
        !           182:                 */
        !           183:                if (page->offset < start || page->offset >= end)
        !           184:                        continue;
        !           185:                
        !           186:                vm_policy_apply(object, page, temperature);
        !           187:        }
        !           188: 
        !           189:        /*
        !           190:         * Recurse over shadow objects.
        !           191:         */
        !           192:        size = end - start;
        !           193:        if ((object->size > 0) && (end - start > object->size))
        !           194:                size = object->size;
        !           195:        start += object->shadow_offset;
        !           196:        end = start + size;
        !           197: 
        !           198:        deactivate_object(object->shadow, start, end, temperature);
        !           199: 
        !           200:        vm_object_unlock(object);
        !           201:        thread_wakeup(object);
        !           202: }
        !           203: 
        !           204: 
        !           205: /*
        !           206:  *  Push a range of pages in a map.
        !           207:  */
        !           208: static void
        !           209: deactivate_range(vm_map_t map, vm_offset_t start, vm_offset_t end, int temp)
        !           210: {
        !           211:        vm_map_entry_t  entry;
        !           212:        vm_object_t     object;
        !           213:        vm_offset_t     tend;
        !           214:        int             offset;
        !           215: 
        !           216:        vm_map_lock_read(map);
        !           217: 
        !           218:        /*
        !           219:         * Push all the pages in this map.
        !           220:         */
        !           221:        for (entry = vm_map_first_entry(map);
        !           222:             entry != vm_map_to_entry(map);
        !           223:             entry = entry->vme_next)
        !           224:        {
        !           225:                /*
        !           226:                 * Recurse over sub-maps.
        !           227:                 */
        !           228:                if (entry->is_a_map || entry->is_sub_map) {
        !           229:                        vm_map_t sub_map;
        !           230:                        sub_map = entry->object.sub_map;
        !           231:                        deactivate_range(sub_map, start, end, temp);
        !           232:                        continue;
        !           233:                }
        !           234:                if (entry->vme_start > end || entry->vme_end <= start)
        !           235:                        continue;
        !           236: 
        !           237:                /*
        !           238:                 * Push the pages we can see in this object chain.
        !           239:                 */
        !           240:                if (entry->vme_start > start)
        !           241:                        start = entry->vme_start;
        !           242: 
        !           243:                if (entry->vme_end < end)
        !           244:                        tend = entry->vme_end;
        !           245:                else
        !           246:                        tend = end;
        !           247: 
        !           248:                object = entry->object.vm_object;
        !           249:                offset = entry->offset + start - entry->vme_start;
        !           250:                deactivate_object(object, offset, offset + tend - start, temp);
        !           251:        }
        !           252:        vm_map_unlock(map);
        !           253: }
        !           254: 
        !           255: 
        !           256: /*
        !           257:  *  Push a range of pages in a map.
        !           258:  */
        !           259: static void
        !           260: set_policy(vm_map_t map, vm_offset_t start, vm_offset_t end, int policy)
        !           261: {
        !           262:        vm_map_entry_t  entry;
        !           263:        vm_object_t     object;
        !           264:        vm_offset_t     tend;
        !           265:        int             offset;
        !           266: 
        !           267:        vm_map_lock_read(map);
        !           268: 
        !           269:        /*
        !           270:         * Push all the pages in this map.
        !           271:         */
        !           272:        for (entry = vm_map_first_entry(map);
        !           273:             entry != vm_map_to_entry(map);
        !           274:             entry = entry->vme_next)
        !           275:        {
        !           276:                /*
        !           277:                 * Recurse over sub-maps.
        !           278:                 */
        !           279:                if (entry->is_a_map || entry->is_sub_map) {
        !           280:                        vm_map_t sub_map;
        !           281:                        sub_map = entry->object.sub_map;
        !           282:                        set_policy(sub_map, start, end, policy);
        !           283:                        continue;
        !           284:                }
        !           285:                if (entry->vme_start > end || entry->vme_end <= start)
        !           286:                        continue;
        !           287: 
        !           288:                /*
        !           289:                 *  Set the policy on the object
        !           290:                 */
        !           291:                object = entry->object.vm_object;
        !           292:                while (object != VM_OBJECT_NULL) {
        !           293:                        object->policy = policy;
        !           294:                        object = object->shadow;
        !           295:                }
        !           296:        }
        !           297:        vm_map_unlock(map);
        !           298: }
        !           299: 
        !           300: 
        !           301: /*
        !           302:  *  Set the policy on a range of pages.  We'd really like to do this on a
        !           303:  *  per-object basis... maybe this should only be applied to pagers?
        !           304:  */
        !           305: kern_return_t
        !           306: vm_set_policy(vm_map_t map, vm_address_t addr, vm_size_t size, int policy)
        !           307: {
        !           308:        if (!map)
        !           309:                return KERN_FAILURE;
        !           310: 
        !           311:        if (size == 0)
        !           312:                size = map->max_offset - map->min_offset;
        !           313: 
        !           314:        if (addr == 0)
        !           315:                addr = map->min_offset;
        !           316: 
        !           317:        set_policy(map, addr, addr + size, policy);
        !           318:        return KERN_SUCCESS;
        !           319: }
        !           320: 
        !           321: 
        !           322: /*
        !           323:  *  Fault a range of pages with a single disk transfer.  Bypass all the normal
        !           324:  *  vm_fault crap.
        !           325:  */
        !           326: kern_return_t
        !           327: vm_fault_range(vm_map_t map, vm_address_t addr, vm_size_t size)
        !           328: {
        !           329:        return KERN_INVALID_ARGUMENT;
        !           330: }
        !           331: 
        !           332: 
        !           333: /*
        !           334:  *  Deactivate a range of pages.
        !           335:  */
        !           336: kern_return_t
        !           337: vm_deactivate(vm_map_t map, vm_address_t addr, vm_size_t size, int temperature)
        !           338: {
        !           339:        if (!map)
        !           340:                return KERN_FAILURE;
        !           341: 
        !           342:        if (size == 0)
        !           343:                size = map->max_offset - map->min_offset;
        !           344: 
        !           345:        if (addr == 0)
        !           346:                addr = map->min_offset;
        !           347: 
        !           348:        deactivate_range(map, addr, size, temperature);
        !           349:        return KERN_SUCCESS;
        !           350: }
        !           351: 
        !           352: 

unix.superglobalmegacorp.com

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