Annotation of kernel/vm/vm_resident.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:  * Mach Operating System
                     27:  * Copyright (c) 1993-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:  *     File:   vm/vm_page.c
                     52:  *     Author: Avadis Tevanian, Jr., Michael Wayne Young
                     53:  *
                     54:  *     Resident memory management module.
                     55:  */
                     56: 
                     57: #import <mach/features.h>
                     58: 
                     59: #include <mach/vm_prot.h>
                     60: #include <kern/counters.h>
                     61: #include <kern/sched_prim.h>
                     62: #include <kern/task.h>
                     63: #include <kern/thread.h>
                     64: #include <mach/vm_statistics.h>
                     65: #include <kern/xpr.h>
                     66: #include <kern/zalloc.h>
                     67: #include <vm/pmap.h>
                     68: #include <vm/vm_map.h>
                     69: #include <vm/vm_page.h>
                     70: #include <vm/vm_pageout.h>
                     71: 
                     72: #include <mach/vm_policy.h>
                     73: 
                     74: /*
                     75:  *     Associated with eacn page of user-allocatable memory is a
                     76:  *     page structure.
                     77:  */
                     78: 
                     79: /*
                     80:  *     These variables record the values returned by vm_page_bootstrap,
                     81:  *     for debugging purposes.  The implementation of pmap_steal_memory
                     82:  *     and pmap_startup here also uses them internally.
                     83:  */
                     84: 
                     85: vm_offset_t virtual_space_start;
                     86: vm_offset_t virtual_space_end;
                     87: 
                     88: /*
                     89:  *     The vm_page_lookup() routine, which provides for fast
                     90:  *     (virtual memory object, offset) to page lookup, employs
                     91:  *     the following hash table.  The vm_page_{insert,remove}
                     92:  *     routines install and remove associations in the table.
                     93:  *     [This table is often called the virtual-to-physical,
                     94:  *     or VP, table.]
                     95:  */
                     96: typedef struct {
                     97:        decl_simple_lock_data(,lock)
                     98:        vm_page_t pages;
                     99: } vm_page_bucket_t;
                    100: 
                    101: vm_page_bucket_t *vm_page_buckets;             /* Array of buckets */
                    102: unsigned int   vm_page_bucket_count = 0;       /* How big is array? */
                    103: unsigned int   vm_page_hash_mask;              /* Mask for hash function */
                    104: 
                    105: /*
                    106:  *     The virtual page size is currently implemented as a runtime
                    107:  *     variable, but is constant once initialized using vm_set_page_size.
                    108:  *     This initialization must be done in the machine-dependent
                    109:  *     bootstrap sequence, before calling other machine-independent
                    110:  *     initializations.
                    111:  *
                    112:  *     All references to the virtual page size outside this
                    113:  *     module must use the PAGE_SIZE constant.
                    114:  */
                    115: vm_size_t      page_size  = 0;
                    116: vm_size_t      page_mask;
                    117: int            page_shift;
                    118: 
                    119: vm_offset_t    map_data;
                    120: vm_size_t      map_data_size;
                    121: 
                    122: vm_offset_t    kentry_data;
                    123: vm_size_t      kentry_data_size;
                    124: 
                    125: extern vm_offset_t     zdata;
                    126: extern vm_size_t       zdata_size;
                    127: 
                    128: queue_head_t   vm_page_queue_free;
                    129: queue_head_t   vm_page_queue_active;
                    130: queue_head_t   vm_page_queue_inactive;
                    131: simple_lock_data_t     vm_page_queue_lock;
                    132: simple_lock_data_t     vm_page_queue_free_lock;
                    133: 
                    134: vm_page_t      vm_page_array;
                    135: long           first_page;
                    136: long           last_page;
                    137: vm_offset_t    first_phys_addr;
                    138: vm_offset_t    last_phys_addr;
                    139: 
                    140: int    vm_page_free_count;
                    141: int    vm_page_active_count;
                    142: int    vm_page_inactive_count;
                    143: int    vm_page_wire_count;
                    144: 
                    145: /*
                    146:  *     Several page replacement parameters are also
                    147:  *     shared with this module, so that page allocation
                    148:  *     (done here in vm_page_alloc) can trigger the
                    149:  *     pageout daemon.
                    150:  */
                    151: int    vm_page_free_target = 0;
                    152: int    vm_page_free_min = 0;
                    153: int    vm_page_inactive_target = 0;
                    154: int    vm_page_free_reserved = 0;
                    155: int    vm_page_laundry_count = 0;
                    156: 
                    157: struct vm_page vm_page_template;
                    158: 
                    159: #if    SHOW_SPACE
                    160: extern int     show_space;
                    161: #endif SHOW_SPACE
                    162: 
                    163: /*
                    164:  *     vm_set_page_size:
                    165:  *
                    166:  *     Sets the page size, perhaps based upon the memory
                    167:  *     size.  Must be called before any use of page-size
                    168:  *     dependent functions.
                    169:  *
                    170:  *     Sets page_shift and page_mask from page_size.
                    171:  */
                    172: void vm_set_page_size(void)
                    173: {
                    174:        page_mask = page_size - 1;
                    175: 
                    176:        if ((page_mask & page_size) != 0)
                    177:                panic("vm_set_page_size: page size not a power of two");
                    178: 
                    179:        for (page_shift = 0; ; page_shift++)
                    180:                if ((1 << page_shift) == page_size)
                    181:                        break;
                    182: }
                    183: 
                    184: /*
                    185:  *     vm_page_startup:
                    186:  *
                    187:  *     Initializes the resident memory module.
                    188:  *
                    189:  *     Allocates memory for the page cells, and
                    190:  *     for the object/offset-to-page hash table headers.
                    191:  *     Each page cell is initialized and placed on the free list.
                    192:  */
                    193: 
                    194: #if    SHOW_SPACE
                    195: #define        PALLOC(name, type, num)                                 \
                    196: MACRO_BEGIN                                                    \
                    197:        (type *)(name) = (type *)                               \
                    198:                vm_alloc_from_regions((num) * sizeof(type),     \
                    199:                                       __alignof__(type));      \
                    200:        bzero((name), (num) * sizeof(type));                    \
                    201:        if (show_space) {                                       \
                    202:                printf(#name " = %d (0x%x) bytes @%x,"          \
                    203:                  " %d cells of %d bytes\n",                    \
                    204:                  (num)*sizeof(type), (num)*sizeof(type), name, \
                    205:                  num, sizeof(type));                           \
                    206:        }                                                       \
                    207: MACRO_END
                    208: 
                    209: #define        PALLOC_SIZE(name, size, type, num)                      \
                    210: MACRO_BEGIN                                                    \
                    211:        (size) = (num) * sizeof(type);                          \
                    212:        (type *)(name) = (type *)                               \
                    213:                vm_alloc_from_regions((size),                   \
                    214:                                      __alignof__(type));       \
                    215:        bzero((name), (size));                                  \
                    216:        if (show_space) {                                       \
                    217:                printf(#name " = %d (0x%x) bytes @%x,"          \
                    218:                  " %d cells of %d bytes\n",                    \
                    219:                  (size), (size), name,                         \
                    220:                  num, sizeof(type));                           \
                    221:        }                                                       \
                    222: MACRO_END
                    223: 
                    224: #define        PALLOC_PAGES(name, type, size)                          \
                    225: MACRO_BEGIN                                                    \
                    226:        (size) = round_page(size);                              \
                    227:        (type *)(name) = (type *)                               \
                    228:                vm_alloc_from_regions((size), PAGE_SIZE);       \
                    229:        bzero((name), (size));                                  \
                    230:        if (show_space) {                                       \
                    231:                printf(#name " = %d (0x%x) bytes @%x,"          \
                    232:                  " %d pages of %d bytes\n",                    \
                    233:                  (size), (size), name,                         \
                    234:                  (size) / PAGE_SIZE, PAGE_SIZE);               \
                    235:        }                                                       \
                    236: MACRO_END
                    237: #else  SHOW_SPACE
                    238: #define        PALLOC(name, type, num)                                 \
                    239: MACRO_BEGIN                                                    \
                    240:        (type *)(name) = (type *)                               \
                    241:                vm_alloc_from_regions((num) * sizeof(type),     \
                    242:                                       __alignof__(type));      \
                    243:        bzero((name), (num) * sizeof(type));                    \
                    244: MACRO_END
                    245: 
                    246: #define        PALLOC_SIZE(name, size, type, num)                      \
                    247: MACRO_BEGIN                                                    \
                    248:        (size) = (num) * sizeof(type);                          \
                    249:        (type *)(name) = (type *)                               \
                    250:                vm_alloc_from_regions((size),                   \
                    251:                                       __alignof__(type));      \
                    252:        bzero((name), (size));                                  \
                    253: MACRO_END
                    254: 
                    255: #define        PALLOC_PAGES(name, type, size)                          \
                    256: MACRO_BEGIN                                                    \
                    257:        (size) = round_page(size);                              \
                    258:        (type *)(name) = (type *)                               \
                    259:                vm_alloc_from_regions((size), PAGE_SIZE);       \
                    260:        bzero((name), (size));                                  \
                    261: MACRO_END
                    262: #endif SHOW_SPACE
                    263: 
                    264: vm_offset_t vm_page_startup(mem_region, num_regions, vavail)
                    265:        mem_region_t            mem_region;
                    266:        int                     num_regions;
                    267:        vm_offset_t             vavail;
                    268: {
                    269:        int                     mem_size;
                    270:        mem_region_t            rp;
                    271:        vm_page_t               m;
                    272:        queue_t                 bucket;
                    273:        int                     i;
                    274:        vm_offset_t             pa;
                    275:        extern vm_offset_t      virtual_avail;
                    276: 
                    277:        /*
                    278:         *      Initialize the vm_page template.
                    279:         */
                    280: 
                    281:        m = &vm_page_template;
                    282:        m->object = VM_OBJECT_NULL;     /* reset later */
                    283:        m->offset = 0;                  /* reset later */
                    284:        m->wire_count = 0;
                    285: 
                    286: #if    OLD_VM_CODE
                    287:        m->clean = TRUE;
                    288:        m->nfspagereq = FALSE;
                    289:        m->copy_on_write = FALSE;
                    290:        m->asyncrw = FALSE;
                    291: #endif
                    292:        m->inactive = FALSE;
                    293:        m->active = FALSE;
                    294:        m->laundry = FALSE;
                    295:        m->free = FALSE;
                    296: 
                    297:        m->busy = TRUE;
                    298:        m->wanted = FALSE;
                    299:        m->tabled = FALSE;
                    300:        m->fictitious = FALSE;
                    301:        m->private = FALSE;
                    302:        m->absent = FALSE;
                    303:        m->error = FALSE;
                    304:        m->dirty = FALSE;
                    305:        m->precious = FALSE;
                    306:        m->reference = FALSE;
                    307: 
                    308:        m->phys_addr = 0;               /* reset later */
                    309: 
                    310:        m->page_lock = VM_PROT_NONE;
                    311:        m->unlock_request = VM_PROT_NONE;
                    312: 
                    313:        /*
                    314:         *      Initialize the locks
                    315:         */
                    316: 
                    317:        simple_lock_init(&vm_page_queue_free_lock);
                    318:        simple_lock_init(&vm_page_queue_lock);
                    319: 
                    320:        /*
                    321:         *      Initialize the queue headers for the free queue,
                    322:         *      the active queue and the inactive queue.
                    323:         */
                    324: 
                    325:        queue_init(&vm_page_queue_free);
                    326:        queue_init(&vm_page_queue_active);
                    327:        queue_init(&vm_page_queue_inactive);
                    328: 
                    329:        /*
                    330:         *      Allocate (and initialize) the virtual-to-physical
                    331:         *      table hash buckets.
                    332:         *
                    333:         *      The number of buckets should be a power of two to
                    334:         *      get a good hash function.  The following computation
                    335:         *      chooses the first power of two that is greater
                    336:         *      than the number of physical pages in the system.
                    337:         */
                    338:        mem_size = 0;
                    339:        for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
                    340:                mem_size += trunc_page(rp->last_phys_addr)
                    341:                  - round_page(rp->first_phys_addr);
                    342:        }
                    343: 
                    344:        if (vm_page_bucket_count == 0) {
                    345:                vm_page_bucket_count = 1;
                    346:                while (vm_page_bucket_count < atop(mem_size))
                    347:                        vm_page_bucket_count <<= 1;
                    348:        }
                    349: 
                    350:        vm_page_hash_mask = vm_page_bucket_count - 1;
                    351: 
                    352:        if (vm_page_hash_mask & vm_page_bucket_count)
                    353:                printf("vm_page_bootstrap: WARNING -- strange page hash\n");
                    354: 
                    355:        PALLOC(vm_page_buckets, vm_page_bucket_t, vm_page_bucket_count);
                    356: 
                    357:        for (i = 0; i < vm_page_bucket_count; i++) {
                    358:                register vm_page_bucket_t *bucket = &vm_page_buckets[i];
                    359: 
                    360:                bucket->pages = VM_PAGE_NULL;
                    361:                simple_lock_init(&bucket->lock);
                    362:        }
                    363: 
                    364:        /*
                    365:         *      Steal pages for some zones that cannot be
                    366:         *      dynamically allocated.
                    367:         */
                    368: #if    1
                    369:        zdata_size = 8*PAGE_SIZE;
                    370:        PALLOC_PAGES(zdata, void, zdata_size);
                    371: #else
                    372:        PALLOC_SIZE(zdata, zdata_size, struct zone, 40);
                    373: #endif
                    374:        PALLOC_SIZE(map_data, map_data_size, struct vm_map, 10);
                    375: 
                    376:        /*
                    377:         *      Allow 2048 kernel map entries... this should be plenty
                    378:         *      since people shouldn't be cluttering up the kernel
                    379:         *      map (they should use their own maps).
                    380:         */
                    381:        PALLOC_SIZE(kentry_data, kentry_data_size, struct vm_map_entry, 2048);
                    382: 
                    383:        /*
                    384:         * First make a pass over each region and allocate
                    385:         * vm_page_arrays.  Later go back and size the pages in the
                    386:         * region (since some of the region may have been taken
                    387:         * by the vm_page_array).
                    388:         */
                    389:        for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
                    390:                ASSERT(rp->first_phys_addr <= rp->last_phys_addr);
                    391:                PALLOC(rp->vm_page_array, struct vm_page,
                    392:                       atop(trunc_page(rp->last_phys_addr) -
                    393:                            round_page(rp->first_phys_addr)));
                    394:        }
                    395:        vm_page_free_count = 0;
                    396:        for (rp = mem_region; rp < &mem_region[num_regions]; rp += 1) {
                    397:                rp->first_phys_addr = round_page(rp->first_phys_addr);
                    398:                rp->last_phys_addr = trunc_page(rp->last_phys_addr);
                    399:                rp->first_page = atop(rp->first_phys_addr);
                    400:                rp->last_page = atop(rp->last_phys_addr);
                    401:                rp->num_pages = rp->last_page - rp->first_page;
                    402:                ASSERT((int)rp->num_pages >= 0);
                    403:                vm_page_free_count += rp->num_pages;
                    404: 
                    405:                m = rp->vm_page_array;
                    406:                pa = rp->first_phys_addr;
                    407: 
                    408:                for (i = 0; i < rp->num_pages; i += 1) {
                    409:                        m->phys_addr = pa;
                    410:                        queue_enter(&vm_page_queue_free, m, vm_page_t, pageq);
                    411:                        m->free = TRUE;
                    412:                        m++;
                    413:                        pa += page_size;
                    414:                }
                    415:        }
                    416: 
                    417:        /*
                    418:         *      Initialize vm_pages_needed lock here - don't wait for pageout
                    419:         *      daemon  XXX
                    420:         */
                    421:        simple_lock_init(&vm_pages_needed_lock);
                    422: 
                    423:        return(virtual_avail);
                    424: }
                    425: 
                    426: /*
                    427:  *     vm_page_hash:
                    428:  *
                    429:  *     Distributes the object/offset key pair among hash buckets.
                    430:  *
                    431:  *     NOTE:   To get a good hash function, the bucket count should
                    432:  *             be a power of two.
                    433:  */
                    434: #define vm_page_hash(object, offset) \
                    435:        (((unsigned int)(vm_offset_t)object + (unsigned int)atop(offset)) \
                    436:                & vm_page_hash_mask)
                    437: 
                    438: /*
                    439:  *     vm_page_insert:         [ internal use only ]
                    440:  *
                    441:  *     Inserts the given mem entry into the object/object-page
                    442:  *     table and object list.
                    443:  *
                    444:  *     The object and page must be locked.
                    445:  */
                    446: 
                    447: void vm_page_insert(
                    448:        register vm_page_t      mem,
                    449:        register vm_object_t    object,
                    450:        register vm_offset_t    offset)
                    451: {
                    452:        register vm_page_bucket_t *bucket;
                    453: 
                    454:        VM_PAGE_CHECK(mem);
                    455: 
                    456:        if (mem->tabled)
                    457:                panic("vm_page_insert");
                    458: 
                    459:        /*
                    460:         *      Record the object/offset pair in this page
                    461:         */
                    462: 
                    463:        mem->object = object;
                    464:        mem->offset = offset;
                    465: 
                    466:        /*
                    467:         *      Insert it into the object_object/offset hash table
                    468:         */
                    469: 
                    470:        bucket = &vm_page_buckets[vm_page_hash(object, offset)];
                    471: {
                    472:        int spl = splimp();
                    473: 
                    474:        simple_lock(&bucket->lock);
                    475:        mem->next = bucket->pages;
                    476:        bucket->pages = mem;
                    477:        simple_unlock(&bucket->lock);
                    478:        (void) splx(spl);
                    479: }
                    480: 
                    481:        /*
                    482:         *      Now link into the object's list of backed pages.
                    483:         */
                    484: 
                    485:        queue_enter(&object->memq, mem, vm_page_t, listq);
                    486:        mem->tabled = TRUE;
                    487: 
                    488:        /*
                    489:         *      Show that the object has one more resident page.
                    490:         */
                    491: 
                    492:        object->resident_page_count++;
                    493: }
                    494: 
                    495: /*
                    496:  *     vm_page_remove:         [ internal use only ]
                    497:  *
                    498:  *     Removes the given mem entry from the object/offset-page
                    499:  *     table and the object page list.
                    500:  *
                    501:  *     The object and page must be locked.
                    502:  */
                    503: 
                    504: void vm_page_remove(
                    505:        register vm_page_t      mem)
                    506: {
                    507:        register vm_page_bucket_t       *bucket;
                    508:        register vm_page_t      this;
                    509: 
                    510:        assert(mem->tabled);
                    511:        VM_PAGE_CHECK(mem);
                    512: 
                    513:        if (!mem->tabled)
                    514:                return;
                    515: 
                    516:        /*
                    517:         *      Remove from the object_object/offset hash table
                    518:         */
                    519: 
                    520:        bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
                    521: {
                    522:        int spl = splimp();
                    523: 
                    524:        simple_lock(&bucket->lock);
                    525:        if ((this = bucket->pages) == mem) {
                    526:                /* optimize for common case */
                    527: 
                    528:                bucket->pages = mem->next;
                    529:        } else {
                    530:                register vm_page_t      *prev;
                    531: 
                    532:                for (prev = &this->next;
                    533:                     (this = *prev) != mem;
                    534:                     prev = &this->next)
                    535:                        continue;
                    536:                *prev = this->next;
                    537:        }
                    538:        simple_unlock(&bucket->lock);
                    539:        splx(spl);
                    540: }
                    541: 
                    542:        /*
                    543:         *      Now remove from the object's list of backed pages.
                    544:         */
                    545: 
                    546:        queue_remove(&mem->object->memq, mem, vm_page_t, listq);
                    547: 
                    548:        /*
                    549:         *      And show that the object has one fewer resident
                    550:         *      page.
                    551:         */
                    552: 
                    553:        mem->object->resident_page_count--;
                    554: 
                    555:        mem->tabled = FALSE;
                    556: }
                    557: 
                    558: /*
                    559:  *     vm_page_lookup:
                    560:  *
                    561:  *     Returns the page associated with the object/offset
                    562:  *     pair specified; if none is found, VM_PAGE_NULL is returned.
                    563:  *
                    564:  *     The object must be locked.  No side effects.
                    565:  */
                    566: 
                    567: vm_page_t vm_page_lookup(
                    568:        register vm_object_t    object,
                    569:        register vm_offset_t    offset)
                    570: {
                    571:        register vm_page_t      mem;
                    572:        register vm_page_bucket_t *bucket;
                    573: 
                    574:        /*
                    575:         *      Search the hash table for this object/offset pair
                    576:         */
                    577: 
                    578:        bucket = &vm_page_buckets[vm_page_hash(object, offset)];
                    579: 
                    580: {
                    581:        int spl = splimp();
                    582: 
                    583:        simple_lock(&bucket->lock);
                    584:        for (mem = bucket->pages; mem != VM_PAGE_NULL; mem = mem->next) {
                    585:                VM_PAGE_CHECK(mem);
                    586:                if ((mem->object == object) && (mem->offset == offset))
                    587:                        break;
                    588:        }
                    589:        simple_unlock(&bucket->lock);
                    590:        splx(spl);
                    591: }
                    592:        return mem;
                    593: }
                    594: 
                    595: /*
                    596:  *     vm_page_rename:
                    597:  *
                    598:  *     Move the given memory entry from its
                    599:  *     current object to the specified target object/offset.
                    600:  *
                    601:  *     The object must be locked.
                    602:  */
                    603: void vm_page_rename(
                    604:        register vm_page_t      mem,
                    605:        register vm_object_t    new_object,
                    606:        vm_offset_t             new_offset)
                    607: {
                    608:        /*
                    609:         *      Changes to mem->object require the page lock because
                    610:         *      the pageout daemon uses that lock to get the object.
                    611:         */
                    612: 
                    613:        vm_page_lock_queues();
                    614:        vm_page_remove(mem);
                    615:        vm_page_insert(mem, new_object, new_offset);
                    616:        vm_page_unlock_queues();
                    617: }
                    618: 
                    619: /*
                    620:  *     vm_page_init:
                    621:  *
                    622:  *     Initialize the given vm_page, entering it into
                    623:  *     the VP table at the given (object, offset),
                    624:  *     and noting its physical address.
                    625:  *
                    626:  *     Implemented using a template set up in vm_page_startup.
                    627:  *     All fields except those passed as arguments are static.
                    628:  */
                    629: void           vm_page_init(mem, object, offset, phys_addr)
                    630:        vm_page_t       mem;
                    631:        vm_object_t     object;
                    632:        vm_offset_t     offset;
                    633:        vm_offset_t     phys_addr;
                    634: {
                    635: #define        vm_page_init(page, object, offset, pa)  { \
                    636:                register \
                    637:                vm_offset_t     a = (pa); \
                    638:                *(page) = vm_page_template; \
                    639:                (page)->phys_addr = a; \
                    640:                vm_page_insert((page), (object), (offset)); \
                    641:        }
                    642: 
                    643:        vm_page_init(mem, object, offset, phys_addr);
                    644: }
                    645: 
                    646: /*
                    647:  *     vm_page_alloc_sequential:
                    648:  *
                    649:  *     vm_page_alloc: is a macro  calling
                    650:  *             vm_page_alloc_sequential(object,offset,TRUE)
                    651:  *
                    652:  *     Allocate and return a memory cell associated
                    653:  *     with this VM object/offset pair. Don't perform sequential 
                    654:  *     access checks if called from ICS.
                    655:  *
                    656:  *     Object must be locked.
                    657:  */
                    658: vm_page_t vm_page_alloc_sequential(object, offset, sequential_unmap)
                    659:        vm_object_t     object;
                    660:        vm_offset_t     offset;
                    661:        boolean_t       sequential_unmap;
                    662: {
                    663:        register vm_page_t      mem;
                    664:        int             spl;
                    665: 
                    666:        spl = splimp();
                    667:        simple_lock(&vm_page_queue_free_lock);
                    668: 
                    669:        if (queue_empty(&vm_page_queue_free)) {
                    670:                simple_unlock(&vm_page_queue_free_lock);
                    671:                splx(spl);
                    672:                return(VM_PAGE_NULL);
                    673:        }
                    674: 
                    675:        if ((vm_page_free_count < vm_page_free_reserved) &&
                    676:                        !current_thread()->vm_privilege) {
                    677:                simple_unlock(&vm_page_queue_free_lock);
                    678:                splx(spl);
                    679:                return(VM_PAGE_NULL);
                    680:        }
                    681: 
                    682:        queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq);
                    683:        mem->free = FALSE;
                    684: 
                    685:        vm_page_free_count--;
                    686:        simple_unlock(&vm_page_queue_free_lock);
                    687:        splx(spl);
                    688: 
                    689:        vm_page_remove(mem);    /* in case it is still in hash table */
                    690: 
                    691:        vm_page_init(mem, object, offset, mem->phys_addr);
                    692: 
                    693:        /*
                    694:         *      Decide if we should poke the pageout daemon.
                    695:         *      We do this if the free count is less than the low
                    696:         *      water mark, or if the free count is less than the high
                    697:         *      water mark (but above the low water mark) and the inactive
                    698:         *      count is less than its target.
                    699:         *
                    700:         *      We don't have the counts locked ... if they change a little,
                    701:         *      it doesn't really matter.
                    702:         */
                    703: 
                    704:        if ((vm_page_free_count < vm_page_free_min) ||
                    705:                        ((vm_page_free_count < vm_page_free_target) &&
                    706:                        (vm_page_inactive_count < vm_page_inactive_target))){
                    707:                thread_wakeup(&vm_pages_needed);
                    708:        }
                    709: 
                    710:        /*
                    711:         *      Detect sequential access and inactivate previous page
                    712:         */
                    713:        if (object->policy & VM_POLICY_SEQUENTIAL && sequential_unmap &&
                    714:            (abs(offset - object->last_alloc) == PAGE_SIZE)) {
                    715:                vm_page_t       last_mem;
                    716: 
                    717:                last_mem = vm_page_lookup(object, object->last_alloc);
                    718:                if (last_mem != VM_PAGE_NULL) {
                    719:                        int     when;
                    720:                        
                    721:                        switch (object->policy) {
                    722:                                case VM_POLICY_SEQ_DEACTIVATE:
                    723:                                        when = VM_DEACTIVATE_SOON;
                    724:                                        break;
                    725:                                case VM_POLICY_SEQ_FREE:
                    726:                                default:
                    727:                                        when = VM_DEACTIVATE_NOW;
                    728:                                        break;
                    729:                        }
                    730:                        vm_policy_apply(object, last_mem, when);
                    731:                }
                    732:        }
                    733: //     else if (object->policy & VM_SEQUENTIAL && sequential_unmap)
                    734: //             object->policy = VM_RANDOM;
                    735: 
                    736:        object->last_alloc = offset;
                    737:        return(mem);
                    738: }
                    739: 
                    740: /*
                    741:  *     vm_page_free:
                    742:  *
                    743:  *     Returns the given page to the free list,
                    744:  *     disassociating it with any VM object.
                    745:  *
                    746:  *     Object and page must be locked prior to entry.
                    747:  */
                    748: void vm_page_free(mem)
                    749:        register vm_page_t      mem;
                    750: {
                    751:        vm_page_remove(mem);
                    752:        if (!mem->free) {
                    753:                vm_page_addfree(mem);
                    754:        }
                    755: }
                    756: 
                    757: void vm_page_addfree(mem)
                    758:        register vm_page_t      mem;
                    759: {
                    760:        if (mem->active) {
                    761:                queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq);
                    762:                mem->active = FALSE;
                    763:                vm_page_active_count--;
                    764:        }
                    765: 
                    766:        if (mem->inactive) {
                    767:                queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq);
                    768:                mem->inactive = FALSE;
                    769:                vm_page_inactive_count--;
                    770:        }
                    771: 
                    772:        if (!mem->fictitious) {
                    773:                int     spl;
                    774: 
                    775:                spl = splimp();
                    776:                simple_lock(&vm_page_queue_free_lock);
                    777:                queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq);
                    778:                mem->free = TRUE;
                    779:                vm_page_free_count++;
                    780:                simple_unlock(&vm_page_queue_free_lock);
                    781:                splx(spl);
                    782:        }
                    783: }
                    784: 
                    785: /*
                    786:  *     vm_page_wire:
                    787:  *
                    788:  *     Mark this page as wired down by yet
                    789:  *     another map, removing it from paging queues
                    790:  *     as necessary.
                    791:  *
                    792:  *     The page queues must be locked.
                    793:  */
                    794: void vm_page_wire(mem)
                    795:        register vm_page_t      mem;
                    796: {
                    797:        VM_PAGE_CHECK(mem);
                    798: 
                    799:        if (mem->wire_count == 0) {
                    800:                if (mem->active) {
                    801:                        queue_remove(&vm_page_queue_active, mem, vm_page_t,
                    802:                                                pageq);
                    803:                        vm_page_active_count--;
                    804:                        mem->active = FALSE;
                    805:                }
                    806:                if (mem->inactive) {
                    807:                        queue_remove(&vm_page_queue_inactive, mem, vm_page_t,
                    808:                                                pageq);
                    809:                        vm_page_inactive_count--;
                    810:                        mem->inactive = FALSE;
                    811:                }
                    812:                if (mem->free) {
                    813:                        queue_remove(&vm_page_queue_free, mem, vm_page_t,
                    814:                                                        pageq);
                    815:                        vm_page_free_count--;
                    816:                        mem->free = FALSE;
                    817:                }
                    818:                vm_page_wire_count++;
                    819:        }
                    820:        mem->wire_count++;
                    821: }
                    822: 
                    823: /*
                    824:  *     vm_page_unwire:
                    825:  *
                    826:  *     Release one wiring of this page, potentially
                    827:  *     enabling it to be paged again.
                    828:  *
                    829:  *     The page queues must be locked.
                    830:  */
                    831: void vm_page_unwire(mem)
                    832:        register vm_page_t      mem;
                    833: {
                    834:        VM_PAGE_CHECK(mem);
                    835: 
                    836:        if (--mem->wire_count == 0) {
                    837:                queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
                    838:                vm_page_active_count++;
                    839:                mem->active = TRUE;
                    840:                vm_page_wire_count--;
                    841:        }
                    842: }
                    843: 
                    844: /*
                    845:  *     _vm_page_deactivate:
                    846:  *
                    847:  *     Internal routine to Returns the given page to the inactive list,
                    848:  *     Page is put at the head of the inactive list if age is TRUE.
                    849:  *     indicating that no physical maps have access
                    850:  *     to this page.  [Used by the physical mapping system.]
                    851:  *
                    852:  *     The page queues must be locked.
                    853:  */
                    854: static void _vm_page_deactivate(m, age)
                    855:        register vm_page_t      m;
                    856:        register boolean_t age;
                    857: {
                    858:        VM_PAGE_CHECK(m);
                    859: 
                    860:        /*
                    861:         *      Only move active pages -- ignore locked or already
                    862:         *      inactive ones.
                    863:         */
                    864: 
                    865:        if (m->active) {
                    866:                pmap_clear_reference(VM_PAGE_TO_PHYS(m));
                    867:                queue_remove(&vm_page_queue_active, m, vm_page_t, pageq);
                    868:                if (age)
                    869:                        queue_enter_first(&vm_page_queue_inactive, m, vm_page_t, pageq);
                    870:                else
                    871:                        queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
                    872:                m->active = FALSE;
                    873:                m->inactive = TRUE;
                    874:                vm_page_active_count--;
                    875:                vm_page_inactive_count++;
                    876:                if (m->clean && pmap_is_modified(VM_PAGE_TO_PHYS(m)))
                    877:                        m->clean = FALSE;
                    878:                m->laundry = !m->clean;
                    879:        }
                    880: }
                    881: 
                    882: /*
                    883:  *     vm_page_deactivate:
                    884:  *
                    885:  *     Returns the given page to the inactive list,
                    886:  *     indicating that no physical maps have access
                    887:  *     to this page.  [Used by the physical mapping system.]
                    888:  *
                    889:  *     The page queues must be locked.
                    890:  */
                    891: void vm_page_deactivate(m)
                    892:        register vm_page_t      m;
                    893: {
                    894:        _vm_page_deactivate(m, FALSE);
                    895: }
                    896: 
                    897: /*
                    898:  *     vm_page_deactivate_first:
                    899:  *
                    900:  *     Returns the given page to the head of inactive list,
                    901:  *     indicating that no physical maps have access
                    902:  *     to this page.  [Used by the physical mapping system.]
                    903:  *
                    904:  *     The page queues must be locked.
                    905:  */
                    906: void vm_page_deactivate_first(m)
                    907:        register vm_page_t      m;
                    908: {
                    909:        _vm_page_deactivate(m, FALSE);
                    910: }
                    911: 
                    912: /*
                    913:  *     vm_page_activate:
                    914:  *
                    915:  *     Put the specified page on the active list (if appropriate).
                    916:  *
                    917:  *     The page queues must be locked.
                    918:  */
                    919: 
                    920: void vm_page_activate(m)
                    921:        register vm_page_t      m;
                    922: {
                    923:        VM_PAGE_CHECK(m);
                    924: 
                    925: 
                    926:        if (m->inactive) {
                    927:                queue_remove(&vm_page_queue_inactive, m, vm_page_t,
                    928:                                                pageq);
                    929:                vm_page_inactive_count--;
                    930:                m->inactive = FALSE;
                    931:        }
                    932:        if (m->free) {
                    933:                queue_remove(&vm_page_queue_free, m, vm_page_t,
                    934:                                                pageq);
                    935:                vm_page_free_count--;
                    936:                m->free = FALSE;
                    937:        }
                    938:        if (m->wire_count == 0) {
                    939:                if (m->active)
                    940:                        panic("vm_page_activate: already active");
                    941: 
                    942:                queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
                    943:                m->active = TRUE;
                    944:                vm_page_active_count++;
                    945:        }
                    946: }
                    947: 
                    948: /*
                    949:  *     vm_page_zero_fill:
                    950:  *
                    951:  *     Zero-fill the specified page.
                    952:  *     Written as a standard pagein routine, to
                    953:  *     be used by the zero-fill object.
                    954:  */
                    955: 
                    956: boolean_t vm_page_zero_fill(m)
                    957:        vm_page_t       m;
                    958: {
                    959:        VM_PAGE_CHECK(m);
                    960: 
                    961:        pmap_zero_page(VM_PAGE_TO_PHYS(m));
                    962:        return(TRUE);
                    963: }
                    964: 
                    965: /*
                    966:  *     vm_page_copy:
                    967:  *
                    968:  *     Copy one page to another
                    969:  */
                    970: 
                    971: void vm_page_copy(src_m, dest_m)
                    972:        vm_page_t       src_m;
                    973:        vm_page_t       dest_m;
                    974: {
                    975:        VM_PAGE_CHECK(src_m);
                    976:        VM_PAGE_CHECK(dest_m);
                    977: 
                    978:        pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
                    979: }
                    980: 
                    981: 
                    982: /*
                    983:  *     vm_page_to_phys:
                    984:  *
                    985:  *     return the physical page, this routine is here so that
                    986:  *     loadable drivers like macfs do not have to deref vm_page_t 
                    987:  *     directly.
                    988:  */
                    989: 
                    990: vm_offset_t
                    991: vm_page_to_phys(m)
                    992:        vm_page_t       m;
                    993: {
                    994:        return(VM_PAGE_TO_PHYS(m));
                    995: }

unix.superglobalmegacorp.com

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