root/uvm/uvm_anon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uvm_anon_init
  2. uvm_analloc
  3. uvm_anfree
  4. uvm_anon_dropswap
  5. uvm_anon_lockloanpg
  6. uvm_anon_pagein

    1 /*      $OpenBSD: uvm_anon.c,v 1.28 2007/06/18 21:51:15 pedro Exp $     */
    2 /*      $NetBSD: uvm_anon.c,v 1.10 2000/11/25 06:27:59 chs Exp $        */
    3 
    4 /*
    5  *
    6  * Copyright (c) 1997 Charles D. Cranor and Washington University.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by Charles D. Cranor and
   20  *      Washington University.
   21  * 4. The name of the author may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   27  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   29  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   33  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   34  */
   35 
   36 /*
   37  * uvm_anon.c: uvm anon ops
   38  */
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/proc.h>
   43 #include <sys/malloc.h>
   44 #include <sys/pool.h>
   45 #include <sys/kernel.h>
   46 
   47 #include <uvm/uvm.h>
   48 #include <uvm/uvm_swap.h>
   49 
   50 struct pool uvm_anon_pool;
   51 
   52 /*
   53  * allocate anons
   54  */
   55 void
   56 uvm_anon_init()
   57 {
   58         pool_init(&uvm_anon_pool, sizeof(struct vm_anon), 0, 0, 0, "anonpl",
   59             &pool_allocator_nointr);
   60         pool_sethiwat(&uvm_anon_pool, uvmexp.free / 16);
   61 }
   62 
   63 /*
   64  * allocate an anon
   65  */
   66 struct vm_anon *
   67 uvm_analloc()
   68 {
   69         struct vm_anon *anon;
   70 
   71         anon = pool_get(&uvm_anon_pool, PR_NOWAIT);
   72         if (anon) {
   73                 simple_lock_init(&anon->an_lock);
   74                 anon->an_ref = 1;
   75                 anon->an_page = NULL;
   76                 anon->an_swslot = 0;
   77                 simple_lock(&anon->an_lock);
   78         }
   79         return(anon);
   80 }
   81 
   82 /*
   83  * uvm_anfree: free a single anon structure
   84  *
   85  * => caller must remove anon from its amap before calling (if it was in
   86  *      an amap).
   87  * => anon must be unlocked and have a zero reference count.
   88  * => we may lock the pageq's.
   89  */
   90 void
   91 uvm_anfree(anon)
   92         struct vm_anon *anon;
   93 {
   94         struct vm_page *pg;
   95         UVMHIST_FUNC("uvm_anfree"); UVMHIST_CALLED(maphist);
   96         UVMHIST_LOG(maphist,"(anon=%p)", anon, 0,0,0);
   97 
   98         /*
   99          * get page
  100          */
  101 
  102         pg = anon->an_page;
  103 
  104         /*
  105          * if there is a resident page and it is loaned, then anon may not
  106          * own it.   call out to uvm_anon_lockpage() to ensure the real owner
  107          * of the page has been identified and locked.
  108          */
  109 
  110         if (pg && pg->loan_count)
  111                 pg = uvm_anon_lockloanpg(anon);
  112 
  113         /*
  114          * if we have a resident page, we must dispose of it before freeing
  115          * the anon.
  116          */
  117 
  118         if (pg) {
  119 
  120                 /*
  121                  * if the page is owned by a uobject (now locked), then we must 
  122                  * kill the loan on the page rather than free it.
  123                  */
  124 
  125                 if (pg->uobject) {
  126                         uvm_lock_pageq();
  127                         KASSERT(pg->loan_count > 0);
  128                         pg->loan_count--;
  129                         pg->uanon = NULL;
  130                         uvm_unlock_pageq();
  131                         simple_unlock(&pg->uobject->vmobjlock);
  132                 } else {
  133 
  134                         /*
  135                          * page has no uobject, so we must be the owner of it.
  136                          *
  137                          * if page is busy then we just mark it as released
  138                          * (who ever has it busy must check for this when they
  139                          * wake up).    if the page is not busy then we can
  140                          * free it now.
  141                          */
  142 
  143                         if ((pg->pg_flags & PG_BUSY) != 0) {
  144                                 /* tell them to dump it when done */
  145                                 atomic_setbits_int(&pg->pg_flags, PG_RELEASED);
  146                                 UVMHIST_LOG(maphist,
  147                                     "  anon %p, page %p: BUSY (released!)", 
  148                                     anon, pg, 0, 0);
  149                                 return;
  150                         } 
  151                         pmap_page_protect(pg, VM_PROT_NONE);
  152                         uvm_lock_pageq();       /* lock out pagedaemon */
  153                         uvm_pagefree(pg);       /* bye bye */
  154                         uvm_unlock_pageq();     /* free the daemon */
  155                         UVMHIST_LOG(maphist,"anon %p, page %p: freed now!",
  156                             anon, pg, 0, 0);
  157                 }
  158         }
  159 
  160         /*
  161          * free any swap resources.
  162          */
  163         uvm_anon_dropswap(anon);
  164 
  165         /*
  166          * now that we've stripped the data areas from the anon, free the anon
  167          * itself!
  168          */
  169         KASSERT(anon->an_page == NULL);
  170         KASSERT(anon->an_swslot == 0);
  171 
  172         pool_put(&uvm_anon_pool, anon);
  173         UVMHIST_LOG(maphist,"<- done!",0,0,0,0);
  174 }
  175 
  176 /*
  177  * uvm_anon_dropswap:  release any swap resources from this anon.
  178  * 
  179  * => anon must be locked or have a reference count of 0.
  180  */
  181 void
  182 uvm_anon_dropswap(anon)
  183         struct vm_anon *anon;
  184 {
  185         UVMHIST_FUNC("uvm_anon_dropswap"); UVMHIST_CALLED(maphist);
  186 
  187         if (anon->an_swslot == 0)
  188                 return;
  189 
  190         UVMHIST_LOG(maphist,"freeing swap for anon %p, paged to swslot 0x%lx",
  191                     anon, anon->an_swslot, 0, 0);
  192         uvm_swap_free(anon->an_swslot, 1);
  193         anon->an_swslot = 0;
  194 
  195         if (anon->an_page == NULL) {
  196                 /* this page is no longer only in swap. */
  197                 simple_lock(&uvm.swap_data_lock);
  198                 uvmexp.swpgonly--;
  199                 simple_unlock(&uvm.swap_data_lock);
  200         } 
  201 }
  202 
  203 /*
  204  * uvm_anon_lockloanpg: given a locked anon, lock its resident page
  205  *
  206  * => anon is locked by caller
  207  * => on return: anon is locked
  208  *               if there is a resident page:
  209  *                      if it has a uobject, it is locked by us
  210  *                      if it is ownerless, we take over as owner
  211  *               we return the resident page (it can change during
  212  *               this function)
  213  * => note that the only time an anon has an ownerless resident page
  214  *      is if the page was loaned from a uvm_object and the uvm_object
  215  *      disowned it
  216  * => this only needs to be called when you want to do an operation
  217  *      on an anon's resident page and that page has a non-zero loan
  218  *      count.
  219  */
  220 struct vm_page *
  221 uvm_anon_lockloanpg(anon)
  222         struct vm_anon *anon;
  223 {
  224         struct vm_page *pg;
  225         boolean_t locked = FALSE;
  226 
  227         /*
  228          * loop while we have a resident page that has a non-zero loan count.
  229          * if we successfully get our lock, we will "break" the loop.
  230          * note that the test for pg->loan_count is not protected -- this
  231          * may produce false positive results.   note that a false positive
  232          * result may cause us to do more work than we need to, but it will
  233          * not produce an incorrect result.
  234          */
  235 
  236         while (((pg = anon->an_page) != NULL) && pg->loan_count != 0) {
  237 
  238                 /*
  239                  * quickly check to see if the page has an object before
  240                  * bothering to lock the page queues.   this may also produce
  241                  * a false positive result, but that's ok because we do a real
  242                  * check after that.
  243                  *
  244                  * XXX: quick check -- worth it?   need volatile?
  245                  */
  246 
  247                 if (pg->uobject) {
  248 
  249                         uvm_lock_pageq();
  250                         if (pg->uobject) {      /* the "real" check */
  251                                 locked =
  252                                     simple_lock_try(&pg->uobject->vmobjlock);
  253                         } else {
  254                                 /* object disowned before we got PQ lock */
  255                                 locked = TRUE;
  256                         }
  257                         uvm_unlock_pageq();
  258 
  259                         /*
  260                          * if we didn't get a lock (try lock failed), then we
  261                          * toggle our anon lock and try again
  262                          */
  263 
  264                         if (!locked) {
  265                                 simple_unlock(&anon->an_lock);
  266 
  267                                 /*
  268                                  * someone locking the object has a chance to
  269                                  * lock us right now
  270                                  */
  271 
  272                                 simple_lock(&anon->an_lock);
  273                                 continue;
  274                         }
  275                 }
  276 
  277                 /*
  278                  * if page is un-owned [i.e. the object dropped its ownership],
  279                  * then we can take over as owner!
  280                  */
  281 
  282                 if (pg->uobject == NULL && (pg->pg_flags & PQ_ANON) == 0) {
  283                         uvm_lock_pageq();
  284                         atomic_setbits_int(&pg->pg_flags, PQ_ANON);
  285                         pg->loan_count--;       /* ... and drop our loan */
  286                         uvm_unlock_pageq();
  287                 }
  288 
  289                 /*
  290                  * we did it!   break the loop
  291                  */
  292 
  293                 break;
  294         }
  295         return(pg);
  296 }
  297 
  298 /*
  299  * fetch an anon's page.
  300  *
  301  * => anon must be locked, and is unlocked upon return.
  302  * => returns TRUE if pagein was aborted due to lack of memory.
  303  */
  304 
  305 boolean_t
  306 uvm_anon_pagein(anon)
  307         struct vm_anon *anon;
  308 {
  309         struct vm_page *pg;
  310         struct uvm_object *uobj;
  311         int rv;
  312 
  313         /* locked: anon */
  314         rv = uvmfault_anonget(NULL, NULL, anon);
  315         /*
  316          * if rv == VM_PAGER_OK, anon is still locked, else anon
  317          * is unlocked
  318          */
  319 
  320         switch (rv) {
  321         case VM_PAGER_OK:
  322                 break;
  323 
  324         case VM_PAGER_ERROR:
  325         case VM_PAGER_REFAULT:
  326 
  327                 /*
  328                  * nothing more to do on errors.
  329                  * VM_PAGER_REFAULT can only mean that the anon was freed,
  330                  * so again there's nothing to do.
  331                  */
  332 
  333                 return FALSE;
  334 
  335         default:
  336 #ifdef DIAGNOSTIC
  337                 panic("anon_pagein: uvmfault_anonget -> %d", rv);
  338 #else
  339                 return FALSE;
  340 #endif
  341         }
  342 
  343         /*
  344          * ok, we've got the page now.
  345          * mark it as dirty, clear its swslot and un-busy it.
  346          */
  347 
  348         pg = anon->an_page;
  349         uobj = pg->uobject;
  350         uvm_swap_free(anon->an_swslot, 1);
  351         anon->an_swslot = 0;
  352         atomic_clearbits_int(&pg->pg_flags, PG_CLEAN);
  353 
  354         /*
  355          * deactivate the page (to put it on a page queue)
  356          */
  357 
  358         pmap_clear_reference(pg);
  359         pmap_page_protect(pg, VM_PROT_NONE);
  360         uvm_lock_pageq();
  361         uvm_pagedeactivate(pg);
  362         uvm_unlock_pageq();
  363 
  364         /*
  365          * unlock the anon and we're done.
  366          */
  367 
  368         simple_unlock(&anon->an_lock);
  369         if (uobj) {
  370                 simple_unlock(&uobj->vmobjlock);
  371         }
  372         return FALSE;
  373 }

/* [<][>][^][v][top][bottom][index][help] */