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

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

unix.superglobalmegacorp.com

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