Annotation of kernel/vm/vm_policy.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) 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.