The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/uvm/uvm_anon.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: uvm_anon.c,v 1.54 2021/03/26 13:40:05 mpi Exp $       */
    2 /*      $NetBSD: uvm_anon.c,v 1.10 2000/11/25 06:27:59 chs Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1997 Charles D. Cranor and Washington University.
    6  * All rights reserved.
    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  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * uvm_anon.c: uvm anon ops
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/malloc.h>
   36 #include <sys/pool.h>
   37 #include <sys/kernel.h>
   38 #include <sys/atomic.h>
   39 
   40 #include <uvm/uvm.h>
   41 #include <uvm/uvm_swap.h>
   42 
   43 struct pool uvm_anon_pool;
   44 
   45 void
   46 uvm_anon_init(void)
   47 {
   48         pool_init(&uvm_anon_pool, sizeof(struct vm_anon), 0, IPL_MPFLOOR,
   49             PR_WAITOK, "anonpl", NULL);
   50         pool_sethiwat(&uvm_anon_pool, uvmexp.free / 16);
   51 }
   52 
   53 /*
   54  * uvm_analloc: allocate a new anon.
   55  *
   56  * => anon will have no lock associated.
   57  */
   58 struct vm_anon *
   59 uvm_analloc(void)
   60 {
   61         struct vm_anon *anon;
   62 
   63         anon = pool_get(&uvm_anon_pool, PR_NOWAIT);
   64         if (anon) {
   65                 anon->an_lock = NULL;
   66                 anon->an_ref = 1;
   67                 anon->an_page = NULL;
   68                 anon->an_swslot = 0;
   69         }
   70         return anon;
   71 }
   72 
   73 /*
   74  * uvm_anfree_list: free a single anon structure
   75  *
   76  * => anon must be removed from the amap (if anon was in an amap).
   77  * => amap must be locked, if anon was owned by amap.
   78  * => we may lock the pageq's.
   79  */
   80 void
   81 uvm_anfree_list(struct vm_anon *anon, struct pglist *pgl)
   82 {
   83         struct vm_page *pg = anon->an_page;
   84 
   85         KASSERT(anon->an_lock == NULL || rw_write_held(anon->an_lock));
   86         KASSERT(anon->an_ref == 0);
   87 
   88         /*
   89          * Dispose of the page, if it is resident.
   90          */
   91         if (pg != NULL) {
   92                 KASSERT(anon->an_lock != NULL);
   93 
   94                 /*
   95                  * If the page is busy, mark it as PG_RELEASED, so
   96                  * that uvm_anon_release(9) would release it later.
   97                  */
   98                 if ((pg->pg_flags & PG_BUSY) != 0) {
   99                         atomic_setbits_int(&pg->pg_flags, PG_RELEASED);
  100                         rw_obj_hold(anon->an_lock);
  101                         return;
  102                 }
  103                 pmap_page_protect(pg, PROT_NONE);
  104                 if (pgl != NULL) {
  105                         /*
  106                          * clean page, and put on on pglist
  107                          * for later freeing.
  108                          */
  109                         uvm_lock_pageq();
  110                         uvm_pageclean(pg);
  111                         uvm_unlock_pageq();
  112                         TAILQ_INSERT_HEAD(pgl, pg, pageq);
  113                 } else {
  114                         uvm_lock_pageq();       /* lock out pagedaemon */
  115                         uvm_pagefree(pg);       /* bye bye */
  116                         uvm_unlock_pageq();     /* free the daemon */
  117                 }
  118         } else {
  119                 if (anon->an_swslot != 0) {
  120                         /* This page is no longer only in swap. */
  121                         KASSERT(uvmexp.swpgonly > 0);
  122                         atomic_dec_int(&uvmexp.swpgonly);
  123                 }
  124         }
  125         anon->an_lock = NULL;
  126 
  127         /*
  128          * Free any swap resources, leave a page replacement hint.
  129          */
  130         uvm_anon_dropswap(anon);
  131 
  132         KASSERT(anon->an_page == NULL);
  133         KASSERT(anon->an_swslot == 0);
  134 
  135         pool_put(&uvm_anon_pool, anon);
  136 }
  137 
  138 /*
  139  * uvm_anwait: wait for memory to become available to allocate an anon.
  140  */
  141 void
  142 uvm_anwait(void)
  143 {
  144         struct vm_anon *anon;
  145 
  146         /* XXX: Want something like pool_wait()? */
  147         anon = pool_get(&uvm_anon_pool, PR_WAITOK);
  148         pool_put(&uvm_anon_pool, anon);
  149 }
  150 
  151 /*
  152  * uvm_anon_pagein: fetch an anon's page.
  153  *
  154  * => anon must be locked, and is unlocked upon return.
  155  * => returns true if pagein was aborted due to lack of memory.
  156  */
  157 
  158 boolean_t
  159 uvm_anon_pagein(struct vm_amap *amap, struct vm_anon *anon)
  160 {
  161         struct vm_page *pg;
  162         int rv;
  163 
  164         KASSERT(rw_write_held(anon->an_lock));
  165         KASSERT(anon->an_lock == amap->am_lock);
  166 
  167         /*
  168          * Get the page of the anon.
  169          */
  170         rv = uvmfault_anonget(NULL, amap, anon);
  171 
  172         switch (rv) {
  173         case VM_PAGER_OK:
  174                 KASSERT(rw_write_held(anon->an_lock));
  175                 break;
  176 
  177         case VM_PAGER_ERROR:
  178         case VM_PAGER_REFAULT:
  179 
  180                 /*
  181                  * Nothing more to do on errors.
  182                  * VM_PAGER_REFAULT  means that the anon was freed.
  183                  */
  184 
  185                 return FALSE;
  186 
  187         default:
  188 #ifdef DIAGNOSTIC
  189                 panic("anon_pagein: uvmfault_anonget -> %d", rv);
  190 #else
  191                 return FALSE;
  192 #endif
  193         }
  194 
  195         /*
  196          * Mark the page as dirty and clear its swslot.
  197          */
  198         pg = anon->an_page;
  199         if (anon->an_swslot > 0) {
  200                 uvm_swap_free(anon->an_swslot, 1);
  201         }
  202         anon->an_swslot = 0;
  203         atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
  204 
  205         /*
  206          * Deactivate the page (to put it on a page queue).
  207          */
  208         pmap_clear_reference(pg);
  209         pmap_page_protect(pg, PROT_NONE);
  210         uvm_lock_pageq();
  211         uvm_pagedeactivate(pg);
  212         uvm_unlock_pageq();
  213         rw_exit(anon->an_lock);
  214 
  215         return FALSE;
  216 }
  217 
  218 /*
  219  * uvm_anon_dropswap: release any swap resources from this anon.
  220  *
  221  * => anon must be locked or have a reference count of 0.
  222  */
  223 void
  224 uvm_anon_dropswap(struct vm_anon *anon)
  225 {
  226         KASSERT(anon->an_ref == 0 || rw_lock_held(anon->an_lock));
  227 
  228         if (anon->an_swslot == 0)
  229                 return;
  230 
  231         uvm_swap_free(anon->an_swslot, 1);
  232         anon->an_swslot = 0;
  233 }
  234 
  235 
  236 /*
  237  * uvm_anon_release: release an anon and its page.
  238  *
  239  * => anon should not have any references.
  240  * => anon must be locked.
  241  */
  242 
  243 void
  244 uvm_anon_release(struct vm_anon *anon)
  245 {
  246         struct vm_page *pg = anon->an_page;
  247         struct rwlock *lock;
  248 
  249         KASSERT(rw_write_held(anon->an_lock));
  250         KASSERT(pg != NULL);
  251         KASSERT((pg->pg_flags & PG_RELEASED) != 0);
  252         KASSERT((pg->pg_flags & PG_BUSY) != 0);
  253         KASSERT(pg->uobject == NULL);
  254         KASSERT(pg->uanon == anon);
  255         KASSERT(anon->an_ref == 0);
  256 
  257         uvm_lock_pageq();
  258         uvm_pagefree(pg);
  259         uvm_unlock_pageq();
  260         KASSERT(anon->an_page == NULL);
  261         lock = anon->an_lock;
  262         uvm_anfree(anon);
  263         rw_exit(lock);
  264         /* Note: extra reference is held for PG_RELEASED case. */
  265         rw_obj_free(lock);
  266 }

Cache object: 905007150a52b2ed7fc7c1fed39eb939


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.