home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / vm / vm_page.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  17.9 KB  |  767 lines

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