Annotation of Net2/vm/vm_page.c, revision 1.1.1.3

1.1       root        1: /* 
                      2:  * Copyright (c) 1991 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * This code is derived from software contributed to Berkeley by
                      6:  * The Mach Operating System project at Carnegie-Mellon University.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by the University of
                     19:  *     California, Berkeley and its contributors.
                     20:  * 4. Neither the name of the University nor the names of its contributors
                     21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
                     36:  *     @(#)vm_page.c   7.4 (Berkeley) 5/7/91
                     37:  *
                     38:  *
                     39:  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
                     40:  * All rights reserved.
                     41:  *
                     42:  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
                     43:  * 
                     44:  * Permission to use, copy, modify and distribute this software and
                     45:  * its documentation is hereby granted, provided that both the copyright
                     46:  * notice and this permission notice appear in all copies of the
                     47:  * software, derivative works or modified versions, and any portions
                     48:  * thereof, and that both notices appear in supporting documentation.
                     49:  * 
                     50:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
                     51:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
                     52:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     53:  * 
                     54:  * Carnegie Mellon requests users of this software to return to
                     55:  *
                     56:  *  Software Distribution Coordinator  or  [email protected]
                     57:  *  School of Computer Science
                     58:  *  Carnegie Mellon University
                     59:  *  Pittsburgh PA 15213-3890
                     60:  *
                     61:  * any improvements or extensions that they make and grant Carnegie the
                     62:  * rights to redistribute these changes.
1.1.1.3 ! root       63:  *
        !            64:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            65:  * --------------------         -----   ----------------------
        !            66:  * CURRENT PATCH LEVEL:         1       00074
        !            67:  * --------------------         -----   ----------------------
        !            68:  *
        !            69:  * 22 Jan 93   Paul Mackerras          Fixed bug where pages got lost
        !            70:  *
1.1       root       71:  */
                     72: 
                     73: /*
                     74:  *     Resident memory management module.
                     75:  */
                     76: 
                     77: #include "param.h"
                     78: 
                     79: #include "vm.h"
                     80: #include "vm_map.h"
                     81: #include "vm_page.h"
                     82: #include "vm_pageout.h"
                     83: 
                     84: /*
                     85:  *     Associated with page of user-allocatable memory is a
                     86:  *     page structure.
                     87:  */
                     88: 
                     89: queue_head_t   *vm_page_buckets;               /* Array of buckets */
                     90: int            vm_page_bucket_count = 0;       /* How big is array? */
                     91: int            vm_page_hash_mask;              /* Mask for hash function */
                     92: simple_lock_data_t     bucket_lock;            /* lock for all buckets XXX */
                     93: 
                     94: vm_size_t      page_size  = 4096;
                     95: vm_size_t      page_mask  = 4095;
                     96: int            page_shift = 12;
                     97: 
                     98: queue_head_t   vm_page_queue_free;
                     99: queue_head_t   vm_page_queue_active;
                    100: queue_head_t   vm_page_queue_inactive;
                    101: simple_lock_data_t     vm_page_queue_lock;
                    102: simple_lock_data_t     vm_page_queue_free_lock;
                    103: 
                    104: vm_page_t      vm_page_array;
                    105: long           first_page;
                    106: long           last_page;
                    107: vm_offset_t    first_phys_addr;
                    108: vm_offset_t    last_phys_addr;
                    109: 
                    110: int    vm_page_free_count;
                    111: int    vm_page_active_count;
                    112: int    vm_page_inactive_count;
                    113: int    vm_page_wire_count;
                    114: int    vm_page_laundry_count;
                    115: 
                    116: int    vm_page_free_target = 0;
                    117: int    vm_page_free_min = 0;
                    118: int    vm_page_inactive_target = 0;
                    119: int    vm_page_free_reserved = 0;
                    120: 
                    121: /*
                    122:  *     vm_set_page_size:
                    123:  *
                    124:  *     Sets the page size, perhaps based upon the memory
                    125:  *     size.  Must be called before any use of page-size
                    126:  *     dependent functions.
                    127:  *
                    128:  *     Sets page_shift and page_mask from page_size.
                    129:  */
                    130: void vm_set_page_size()
                    131: {
                    132:        page_mask = page_size - 1;
                    133: 
                    134:        if ((page_mask & page_size) != 0)
                    135:                panic("vm_set_page_size: page size not a power of two");
                    136: 
                    137:        for (page_shift = 0; ; page_shift++)
                    138:                if ((1 << page_shift) == page_size)
                    139:                        break;
                    140: }
                    141: 
                    142: 
                    143: /*
                    144:  *     vm_page_startup:
                    145:  *
                    146:  *     Initializes the resident memory module.
                    147:  *
                    148:  *     Allocates memory for the page cells, and
                    149:  *     for the object/offset-to-page hash table headers.
                    150:  *     Each page cell is initialized and placed on the free list.
                    151:  */
                    152: vm_offset_t vm_page_startup(start, end, vaddr)
                    153:        register vm_offset_t    start;
                    154:        vm_offset_t     end;
                    155:        register vm_offset_t    vaddr;
                    156: {
                    157:        register vm_offset_t    mapped;
                    158:        register vm_page_t      m;
                    159:        register queue_t        bucket;
                    160:        vm_size_t               npages;
                    161:        register vm_offset_t    new_start;
                    162:        int                     i;
                    163:        vm_offset_t             pa;
                    164: 
                    165:        extern  vm_offset_t     kentry_data;
                    166:        extern  vm_size_t       kentry_data_size;
                    167: 
                    168: 
                    169:        /*
                    170:         *      Initialize the locks
                    171:         */
                    172: 
                    173:        simple_lock_init(&vm_page_queue_free_lock);
                    174:        simple_lock_init(&vm_page_queue_lock);
                    175: 
                    176:        /*
                    177:         *      Initialize the queue headers for the free queue,
                    178:         *      the active queue and the inactive queue.
                    179:         */
                    180: 
                    181:        queue_init(&vm_page_queue_free);
                    182:        queue_init(&vm_page_queue_active);
                    183:        queue_init(&vm_page_queue_inactive);
                    184: 
                    185:        /*
                    186:         *      Allocate (and initialize) the hash table buckets.
                    187:         *
                    188:         *      The number of buckets MUST BE a power of 2, and
                    189:         *      the actual value is the next power of 2 greater
                    190:         *      than the number of physical pages in the system.
                    191:         *
                    192:         *      Note:
                    193:         *              This computation can be tweaked if desired.
                    194:         */
                    195: 
                    196:        vm_page_buckets = (queue_t) vaddr;
                    197:        bucket = vm_page_buckets;
                    198:        if (vm_page_bucket_count == 0) {
                    199:                vm_page_bucket_count = 1;
                    200:                while (vm_page_bucket_count < atop(end - start))
                    201:                        vm_page_bucket_count <<= 1;
                    202:        }
                    203: 
                    204:        vm_page_hash_mask = vm_page_bucket_count - 1;
                    205: 
                    206:        /*
                    207:         *      Validate these addresses.
                    208:         */
                    209: 
                    210:        new_start = round_page(((queue_t)start) + vm_page_bucket_count);
                    211:        mapped = vaddr;
                    212:        vaddr = pmap_map(mapped, start, new_start,
                    213:                        VM_PROT_READ|VM_PROT_WRITE);
                    214:        start = new_start;
1.1.1.2   root      215:        bzero((caddr_t) mapped, vaddr - mapped);
1.1       root      216:        mapped = vaddr;
                    217: 
                    218:        for (i = vm_page_bucket_count; i--;) {
                    219:                queue_init(bucket);
                    220:                bucket++;
                    221:        }
                    222: 
                    223:        simple_lock_init(&bucket_lock);
                    224: 
                    225:        /*
                    226:         *      round (or truncate) the addresses to our page size.
                    227:         */
                    228: 
                    229:        end = trunc_page(end);
                    230: 
                    231:        /*
                    232:         *      Pre-allocate maps and map entries that cannot be dynamically
                    233:         *      allocated via malloc().  The maps include the kernel_map and
                    234:         *      kmem_map which must be initialized before malloc() will
                    235:         *      work (obviously).  Also could include pager maps which would
                    236:         *      be allocated before kmeminit.
                    237:         *
                    238:         *      Allow some kernel map entries... this should be plenty
                    239:         *      since people shouldn't be cluttering up the kernel
                    240:         *      map (they should use their own maps).
                    241:         */
                    242: 
                    243:        kentry_data_size = MAX_KMAP * sizeof(struct vm_map) +
                    244:                           MAX_KMAPENT * sizeof(struct vm_map_entry);
                    245:        kentry_data_size = round_page(kentry_data_size);
                    246:        kentry_data = (vm_offset_t) vaddr;
                    247:        vaddr += kentry_data_size;
                    248: 
                    249:        /*
                    250:         *      Validate these zone addresses.
                    251:         */
                    252: 
                    253:        new_start = start + (vaddr - mapped);
                    254:        pmap_map(mapped, start, new_start, VM_PROT_READ|VM_PROT_WRITE);
1.1.1.2   root      255:        bzero((caddr_t) mapped, (vaddr - mapped));
1.1       root      256:        mapped = vaddr;
                    257:        start = new_start;
                    258: 
                    259:        /*
                    260:         *      Compute the number of pages of memory that will be
                    261:         *      available for use (taking into account the overhead
                    262:         *      of a page structure per page).
                    263:         */
                    264: 
                    265:        vm_page_free_count = npages =
                    266:                (end - start)/(PAGE_SIZE + sizeof(struct vm_page));
                    267: 
                    268:        /*
                    269:         *      Initialize the mem entry structures now, and
                    270:         *      put them in the free queue.
                    271:         */
                    272: 
                    273:        m = vm_page_array = (vm_page_t) vaddr;
                    274:        first_page = start;
                    275:        first_page += npages*sizeof(struct vm_page);
                    276:        first_page = atop(round_page(first_page));
                    277:        last_page  = first_page + npages - 1;
                    278: 
                    279:        first_phys_addr = ptoa(first_page);
                    280:        last_phys_addr  = ptoa(last_page) + page_mask;
                    281: 
                    282:        /*
                    283:         *      Validate these addresses.
                    284:         */
                    285: 
                    286:        new_start = start + (round_page(m + npages) - mapped);
                    287:        mapped = pmap_map(mapped, start, new_start,
                    288:                        VM_PROT_READ|VM_PROT_WRITE);
                    289:        start = new_start;
                    290: 
                    291:        /*
                    292:         *      Clear all of the page structures
                    293:         */
1.1.1.2   root      294:        bzero((caddr_t)m, npages * sizeof(*m));
1.1       root      295: 
                    296:        pa = first_phys_addr;
                    297:        while (npages--) {
                    298:                m->copy_on_write = FALSE;
                    299:                m->wanted = FALSE;
                    300:                m->inactive = FALSE;
                    301:                m->active = FALSE;
                    302:                m->busy = FALSE;
                    303:                m->object = NULL;
                    304:                m->phys_addr = pa;
                    305:                queue_enter(&vm_page_queue_free, m, vm_page_t, pageq);
                    306:                m++;
                    307:                pa += PAGE_SIZE;
                    308:        }
                    309: 
                    310:        /*
                    311:         *      Initialize vm_pages_needed lock here - don't wait for pageout
                    312:         *      daemon  XXX
                    313:         */
                    314:        simple_lock_init(&vm_pages_needed_lock);
                    315: 
                    316:        return(mapped);
                    317: }
                    318: 
                    319: /*
                    320:  *     vm_page_hash:
                    321:  *
                    322:  *     Distributes the object/offset key pair among hash buckets.
                    323:  *
                    324:  *     NOTE:  This macro depends on vm_page_bucket_count being a power of 2.
                    325:  */
                    326: #define vm_page_hash(object, offset) \
                    327:        (((unsigned)object+(unsigned)atop(offset))&vm_page_hash_mask)
                    328: 
                    329: /*
                    330:  *     vm_page_insert:         [ internal use only ]
                    331:  *
                    332:  *     Inserts the given mem entry into the object/object-page
                    333:  *     table and object list.
                    334:  *
                    335:  *     The object and page must be locked.
                    336:  */
                    337: 
                    338: void vm_page_insert(mem, object, offset)
                    339:        register vm_page_t      mem;
                    340:        register vm_object_t    object;
                    341:        register vm_offset_t    offset;
                    342: {
                    343:        register queue_t        bucket;
                    344:        int                     spl;
                    345: 
                    346:        VM_PAGE_CHECK(mem);
                    347: 
                    348:        if (mem->tabled)
                    349:                panic("vm_page_insert: already inserted");
                    350: 
                    351:        /*
                    352:         *      Record the object/offset pair in this page
                    353:         */
                    354: 
                    355:        mem->object = object;
                    356:        mem->offset = offset;
                    357: 
                    358:        /*
                    359:         *      Insert it into the object_object/offset hash table
                    360:         */
                    361: 
                    362:        bucket = &vm_page_buckets[vm_page_hash(object, offset)];
                    363:        spl = splimp();
                    364:        simple_lock(&bucket_lock);
                    365:        queue_enter(bucket, mem, vm_page_t, hashq);
                    366:        simple_unlock(&bucket_lock);
                    367:        (void) splx(spl);
                    368: 
                    369:        /*
                    370:         *      Now link into the object's list of backed pages.
                    371:         */
                    372: 
                    373:        queue_enter(&object->memq, mem, vm_page_t, listq);
                    374:        mem->tabled = TRUE;
                    375: 
                    376:        /*
                    377:         *      And show that the object has one more resident
                    378:         *      page.
                    379:         */
                    380: 
                    381:        object->resident_page_count++;
                    382: }
                    383: 
                    384: /*
                    385:  *     vm_page_remove:         [ internal use only ]
                    386:  *
                    387:  *     Removes the given mem entry from the object/offset-page
                    388:  *     table and the object page list.
                    389:  *
                    390:  *     The object and page must be locked.
                    391:  */
                    392: 
                    393: void vm_page_remove(mem)
                    394:        register vm_page_t      mem;
                    395: {
                    396:        register queue_t        bucket;
                    397:        int                     spl;
                    398: 
                    399:        VM_PAGE_CHECK(mem);
                    400: 
                    401:        if (!mem->tabled)
                    402:                return;
                    403: 
                    404:        /*
                    405:         *      Remove from the object_object/offset hash table
                    406:         */
                    407: 
                    408:        bucket = &vm_page_buckets[vm_page_hash(mem->object, mem->offset)];
                    409:        spl = splimp();
                    410:        simple_lock(&bucket_lock);
                    411:        queue_remove(bucket, mem, vm_page_t, hashq);
                    412:        simple_unlock(&bucket_lock);
                    413:        (void) splx(spl);
                    414: 
                    415:        /*
                    416:         *      Now remove from the object's list of backed pages.
                    417:         */
                    418: 
                    419:        queue_remove(&mem->object->memq, mem, vm_page_t, listq);
                    420: 
                    421:        /*
                    422:         *      And show that the object has one fewer resident
                    423:         *      page.
                    424:         */
                    425: 
                    426:        mem->object->resident_page_count--;
                    427: 
                    428:        mem->tabled = FALSE;
                    429: }
                    430: 
                    431: /*
                    432:  *     vm_page_lookup:
                    433:  *
                    434:  *     Returns the page associated with the object/offset
                    435:  *     pair specified; if none is found, NULL is returned.
                    436:  *
                    437:  *     The object must be locked.  No side effects.
                    438:  */
                    439: 
                    440: vm_page_t vm_page_lookup(object, offset)
                    441:        register vm_object_t    object;
                    442:        register vm_offset_t    offset;
                    443: {
                    444:        register vm_page_t      mem;
                    445:        register queue_t        bucket;
                    446:        int                     spl;
                    447: 
                    448:        /*
                    449:         *      Search the hash table for this object/offset pair
                    450:         */
                    451: 
                    452:        bucket = &vm_page_buckets[vm_page_hash(object, offset)];
                    453: 
                    454:        spl = splimp();
                    455:        simple_lock(&bucket_lock);
                    456:        mem = (vm_page_t) queue_first(bucket);
                    457:        while (!queue_end(bucket, (queue_entry_t) mem)) {
                    458:                VM_PAGE_CHECK(mem);
                    459:                if ((mem->object == object) && (mem->offset == offset)) {
                    460:                        simple_unlock(&bucket_lock);
                    461:                        splx(spl);
                    462:                        return(mem);
                    463:                }
                    464:                mem = (vm_page_t) queue_next(&mem->hashq);
                    465:        }
                    466: 
                    467:        simple_unlock(&bucket_lock);
                    468:        splx(spl);
                    469:        return(NULL);
                    470: }
                    471: 
                    472: /*
                    473:  *     vm_page_rename:
                    474:  *
                    475:  *     Move the given memory entry from its
                    476:  *     current object to the specified target object/offset.
                    477:  *
                    478:  *     The object must be locked.
                    479:  */
                    480: void vm_page_rename(mem, new_object, new_offset)
                    481:        register vm_page_t      mem;
                    482:        register vm_object_t    new_object;
                    483:        vm_offset_t             new_offset;
                    484: {
                    485:        if (mem->object == new_object)
                    486:                return;
                    487: 
                    488:        vm_page_lock_queues();  /* keep page from moving out from
                    489:                                   under pageout daemon */
                    490:        vm_page_remove(mem);
                    491:        vm_page_insert(mem, new_object, new_offset);
                    492:        vm_page_unlock_queues();
                    493: }
                    494: 
                    495: void           vm_page_init(mem, object, offset)
                    496:        vm_page_t       mem;
                    497:        vm_object_t     object;
                    498:        vm_offset_t     offset;
                    499: {
                    500: #ifdef DEBUG
                    501: #define        vm_page_init(mem, object, offset)  {\
                    502:                (mem)->busy = TRUE; \
                    503:                (mem)->tabled = FALSE; \
                    504:                vm_page_insert((mem), (object), (offset)); \
                    505:                (mem)->absent = FALSE; \
                    506:                (mem)->fictitious = FALSE; \
                    507:                (mem)->page_lock = VM_PROT_NONE; \
                    508:                (mem)->unlock_request = VM_PROT_NONE; \
                    509:                (mem)->laundry = FALSE; \
                    510:                (mem)->active = FALSE; \
                    511:                (mem)->inactive = FALSE; \
                    512:                (mem)->wire_count = 0; \
                    513:                (mem)->clean = TRUE; \
                    514:                (mem)->copy_on_write = FALSE; \
                    515:                (mem)->fake = TRUE; \
                    516:                (mem)->pagerowned = FALSE; \
                    517:                (mem)->ptpage = FALSE; \
                    518:        }
                    519: #else
                    520: #define        vm_page_init(mem, object, offset)  {\
                    521:                (mem)->busy = TRUE; \
                    522:                (mem)->tabled = FALSE; \
                    523:                vm_page_insert((mem), (object), (offset)); \
                    524:                (mem)->absent = FALSE; \
                    525:                (mem)->fictitious = FALSE; \
                    526:                (mem)->page_lock = VM_PROT_NONE; \
                    527:                (mem)->unlock_request = VM_PROT_NONE; \
                    528:                (mem)->laundry = FALSE; \
                    529:                (mem)->active = FALSE; \
                    530:                (mem)->inactive = FALSE; \
                    531:                (mem)->wire_count = 0; \
                    532:                (mem)->clean = TRUE; \
                    533:                (mem)->copy_on_write = FALSE; \
                    534:                (mem)->fake = TRUE; \
                    535:        }
                    536: #endif
                    537: 
                    538:        vm_page_init(mem, object, offset);
                    539: }
                    540: 
                    541: /*
                    542:  *     vm_page_alloc:
                    543:  *
                    544:  *     Allocate and return a memory cell associated
                    545:  *     with this VM object/offset pair.
                    546:  *
                    547:  *     Object must be locked.
                    548:  */
                    549: vm_page_t vm_page_alloc(object, offset)
                    550:        vm_object_t     object;
                    551:        vm_offset_t     offset;
                    552: {
                    553:        register vm_page_t      mem;
                    554:        int             spl;
                    555: 
                    556:        spl = splimp();                         /* XXX */
                    557:        simple_lock(&vm_page_queue_free_lock);
                    558:        if (queue_empty(&vm_page_queue_free)) {
                    559:                simple_unlock(&vm_page_queue_free_lock);
                    560:                splx(spl);
                    561:                return(NULL);
                    562:        }
                    563: 
                    564:        queue_remove_first(&vm_page_queue_free, mem, vm_page_t, pageq);
                    565: 
                    566:        vm_page_free_count--;
                    567:        simple_unlock(&vm_page_queue_free_lock);
                    568:        splx(spl);
                    569: 
                    570:        vm_page_init(mem, object, offset);
                    571: 
                    572:        /*
                    573:         *      Decide if we should poke the pageout daemon.
                    574:         *      We do this if the free count is less than the low
                    575:         *      water mark, or if the free count is less than the high
                    576:         *      water mark (but above the low water mark) and the inactive
                    577:         *      count is less than its target.
                    578:         *
                    579:         *      We don't have the counts locked ... if they change a little,
                    580:         *      it doesn't really matter.
                    581:         */
                    582: 
                    583:        if ((vm_page_free_count < vm_page_free_min) ||
                    584:                        ((vm_page_free_count < vm_page_free_target) &&
                    585:                        (vm_page_inactive_count < vm_page_inactive_target)))
                    586:                thread_wakeup(&vm_pages_needed);
                    587:        return(mem);
                    588: }
                    589: 
                    590: /*
                    591:  *     vm_page_free:
                    592:  *
                    593:  *     Returns the given page to the free list,
                    594:  *     disassociating it with any VM object.
                    595:  *
                    596:  *     Object and page must be locked prior to entry.
                    597:  */
                    598: void vm_page_free(mem)
                    599:        register vm_page_t      mem;
                    600: {
                    601:        vm_page_remove(mem);
                    602:        if (mem->active) {
                    603:                queue_remove(&vm_page_queue_active, mem, vm_page_t, pageq);
                    604:                mem->active = FALSE;
                    605:                vm_page_active_count--;
                    606:        }
                    607: 
                    608:        if (mem->inactive) {
                    609:                queue_remove(&vm_page_queue_inactive, mem, vm_page_t, pageq);
                    610:                mem->inactive = FALSE;
                    611:                vm_page_inactive_count--;
                    612:        }
                    613: 
                    614:        if (!mem->fictitious) {
                    615:                int     spl;
                    616: 
                    617:                spl = splimp();
                    618:                simple_lock(&vm_page_queue_free_lock);
                    619:                queue_enter(&vm_page_queue_free, mem, vm_page_t, pageq);
                    620: 
                    621:                vm_page_free_count++;
                    622:                simple_unlock(&vm_page_queue_free_lock);
                    623:                splx(spl);
                    624:        }
                    625: }
                    626: 
                    627: /*
                    628:  *     vm_page_wire:
                    629:  *
                    630:  *     Mark this page as wired down by yet
                    631:  *     another map, removing it from paging queues
                    632:  *     as necessary.
                    633:  *
                    634:  *     The page queues must be locked.
                    635:  */
                    636: void vm_page_wire(mem)
                    637:        register vm_page_t      mem;
                    638: {
                    639:        VM_PAGE_CHECK(mem);
                    640: 
                    641:        if (mem->wire_count == 0) {
                    642:                if (mem->active) {
                    643:                        queue_remove(&vm_page_queue_active, mem, vm_page_t,
                    644:                                                pageq);
                    645:                        vm_page_active_count--;
                    646:                        mem->active = FALSE;
                    647:                }
                    648:                if (mem->inactive) {
                    649:                        queue_remove(&vm_page_queue_inactive, mem, vm_page_t,
                    650:                                                pageq);
                    651:                        vm_page_inactive_count--;
                    652:                        mem->inactive = FALSE;
                    653:                }
                    654:                vm_page_wire_count++;
                    655:        }
                    656:        mem->wire_count++;
                    657: }
                    658: 
                    659: /*
                    660:  *     vm_page_unwire:
                    661:  *
                    662:  *     Release one wiring of this page, potentially
                    663:  *     enabling it to be paged again.
                    664:  *
                    665:  *     The page queues must be locked.
                    666:  */
                    667: void vm_page_unwire(mem)
                    668:        register vm_page_t      mem;
                    669: {
                    670:        VM_PAGE_CHECK(mem);
                    671: 
                    672:        mem->wire_count--;
                    673:        if (mem->wire_count == 0) {
                    674:                queue_enter(&vm_page_queue_active, mem, vm_page_t, pageq);
                    675:                vm_page_active_count++;
                    676:                mem->active = TRUE;
                    677:                vm_page_wire_count--;
                    678:        }
                    679: }
                    680: 
                    681: /*
                    682:  *     vm_page_deactivate:
                    683:  *
                    684:  *     Returns the given page to the inactive list,
                    685:  *     indicating that no physical maps have access
                    686:  *     to this page.  [Used by the physical mapping system.]
                    687:  *
                    688:  *     The page queues must be locked.
                    689:  */
                    690: void vm_page_deactivate(m)
                    691:        register vm_page_t      m;
                    692: {
                    693:        VM_PAGE_CHECK(m);
                    694: 
                    695:        /*
                    696:         *      Only move active pages -- ignore locked or already
                    697:         *      inactive ones.
1.1.1.3 ! root      698:         *
        !           699:         *      XXX: sometimes we get pages which aren't wired down
        !           700:         *      or on any queue - we need to put them on the inactive
        !           701:         *      queue also, otherwise we lose track of them.
        !           702:         *      Paul Mackerras ([email protected]) 9-Jan-93.
1.1       root      703:         */
                    704: 
1.1.1.3 ! root      705:        if (!m->inactive && m->wire_count == 0) {
1.1       root      706:                pmap_clear_reference(VM_PAGE_TO_PHYS(m));
1.1.1.3 ! root      707:                if (m->active) {
        !           708:                        queue_remove(&vm_page_queue_active, m, vm_page_t, pageq);
        !           709:                        m->active = FALSE;
        !           710:                        vm_page_active_count--;
        !           711:                }
1.1       root      712:                queue_enter(&vm_page_queue_inactive, m, vm_page_t, pageq);
                    713:                m->inactive = TRUE;
                    714:                vm_page_inactive_count++;
                    715:                if (pmap_is_modified(VM_PAGE_TO_PHYS(m)))
                    716:                        m->clean = FALSE;
                    717:                m->laundry = !m->clean;
                    718:        }
                    719: }
                    720: 
                    721: /*
                    722:  *     vm_page_activate:
                    723:  *
                    724:  *     Put the specified page on the active list (if appropriate).
                    725:  *
                    726:  *     The page queues must be locked.
                    727:  */
                    728: 
                    729: void vm_page_activate(m)
                    730:        register vm_page_t      m;
                    731: {
                    732:        VM_PAGE_CHECK(m);
                    733: 
                    734:        if (m->inactive) {
                    735:                queue_remove(&vm_page_queue_inactive, m, vm_page_t,
                    736:                                                pageq);
                    737:                vm_page_inactive_count--;
                    738:                m->inactive = FALSE;
                    739:        }
                    740:        if (m->wire_count == 0) {
                    741:                if (m->active)
                    742:                        panic("vm_page_activate: already active");
                    743: 
                    744:                queue_enter(&vm_page_queue_active, m, vm_page_t, pageq);
                    745:                m->active = TRUE;
                    746:                vm_page_active_count++;
                    747:        }
                    748: }
                    749: 
                    750: /*
                    751:  *     vm_page_zero_fill:
                    752:  *
                    753:  *     Zero-fill the specified page.
                    754:  *     Written as a standard pagein routine, to
                    755:  *     be used by the zero-fill object.
                    756:  */
                    757: 
                    758: boolean_t vm_page_zero_fill(m)
                    759:        vm_page_t       m;
                    760: {
                    761:        VM_PAGE_CHECK(m);
                    762: 
                    763:        pmap_zero_page(VM_PAGE_TO_PHYS(m));
                    764:        return(TRUE);
                    765: }
                    766: 
                    767: /*
                    768:  *     vm_page_copy:
                    769:  *
                    770:  *     Copy one page to another
                    771:  */
                    772: 
                    773: void vm_page_copy(src_m, dest_m)
                    774:        vm_page_t       src_m;
                    775:        vm_page_t       dest_m;
                    776: {
                    777:        VM_PAGE_CHECK(src_m);
                    778:        VM_PAGE_CHECK(dest_m);
                    779: 
                    780:        pmap_copy_page(VM_PAGE_TO_PHYS(src_m), VM_PAGE_TO_PHYS(dest_m));
                    781: }

unix.superglobalmegacorp.com

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