[BACK]Return to uvm_loan.c CVS log [TXT][DIR] Up to [local] / sys / uvm

Annotation of sys/uvm/uvm_loan.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uvm_loan.c,v 1.28 2007/06/18 21:51:15 pedro Exp $     */
                      2: /*     $NetBSD: uvm_loan.c,v 1.22 2000/06/27 17:29:25 mrg 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:  * from: Id: uvm_loan.c,v 1.1.6.4 1998/02/06 05:08:43 chs Exp
                     36:  */
                     37:
                     38: /*
                     39:  * uvm_loan.c: page loanout handler
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/malloc.h>
                     47: #include <sys/mman.h>
                     48:
                     49: #include <uvm/uvm.h>
                     50:
                     51: /*
                     52:  * "loaned" pages are pages which are (read-only, copy-on-write) loaned
                     53:  * from the VM system to other parts of the kernel.   this allows page
                     54:  * copying to be avoided (e.g. you can loan pages from objs/anons to
                     55:  * the mbuf system).
                     56:  *
                     57:  * there are 3 types of loans possible:
                     58:  *  O->K  uvm_object page to wired kernel page (e.g. mbuf data area)
                     59:  *  A->K  anon page to wired kernel page (e.g. mbuf data area)
                     60:  *  O->A  uvm_object to anon loan (e.g. vnode page to an anon)
                     61:  * note that it possible to have an O page loaned to both an A and K
                     62:  * at the same time.
                     63:  *
                     64:  * loans are tracked by pg->loan_count.  an O->A page will have both
                     65:  * a uvm_object and a vm_anon, but PQ_ANON will not be set.   this sort
                     66:  * of page is considered "owned" by the uvm_object (not the anon).
                     67:  *
                     68:  * each loan of a page to the kernel bumps the pg->wire_count.  the
                     69:  * kernel mappings for these pages will be read-only and wired.  since
                     70:  * the page will also be wired, it will not be a candidate for pageout,
                     71:  * and thus will never be pmap_page_protect()'d with VM_PROT_NONE.  a
                     72:  * write fault in the kernel to one of these pages will not cause
                     73:  * copy-on-write.  instead, the page fault is considered fatal.  this
                     74:  * is because the kernel mapping will have no way to look up the
                     75:  * object/anon which the page is owned by.  this is a good side-effect,
                     76:  * since a kernel write to a loaned page is an error.
                     77:  *
                     78:  * owners that want to free their pages and discover that they are
                     79:  * loaned out simply "disown" them (the page becomes an orphan).  these
                     80:  * pages should be freed when the last loan is dropped.   in some cases
                     81:  * an anon may "adopt" an orphaned page.
                     82:  *
                     83:  * locking: to read pg->loan_count either the owner or the page queues
                     84:  * must be locked.   to modify pg->loan_count, both the owner of the page
                     85:  * and the PQs must be locked.   pg->flags is (as always) locked by
                     86:  * the owner of the page.
                     87:  *
                     88:  * note that locking from the "loaned" side is tricky since the object
                     89:  * getting the loaned page has no reference to the page's owner and thus
                     90:  * the owner could "die" at any time.   in order to prevent the owner
                     91:  * from dying the page queues should be locked.   this forces us to sometimes
                     92:  * use "try" locking.
                     93:  *
                     94:  * loans are typically broken by the following events:
                     95:  *  1. write fault to a loaned page
                     96:  *  2. pageout of clean+inactive O->A loaned page
                     97:  *  3. owner frees page (e.g. pager flush)
                     98:  *
                     99:  * note that loaning a page causes all mappings of the page to become
                    100:  * read-only (via pmap_page_protect).   this could have an unexpected
                    101:  * effect on normal "wired" pages if one is not careful (XXX).
                    102:  */
                    103:
                    104: /*
                    105:  * local prototypes
                    106:  */
                    107:
                    108: static int     uvm_loananon(struct uvm_faultinfo *, void ***,
                    109:                                int, struct vm_anon *);
                    110: static int     uvm_loanentry(struct uvm_faultinfo *, void ***, int);
                    111: static int     uvm_loanuobj(struct uvm_faultinfo *, void ***,
                    112:                                int, vaddr_t);
                    113: static int     uvm_loanzero(struct uvm_faultinfo *, void ***, int);
                    114:
                    115: /*
                    116:  * inlines
                    117:  */
                    118:
                    119: /*
                    120:  * uvm_loanentry: loan out pages in a map entry (helper fn for uvm_loan())
                    121:  *
                    122:  * => "ufi" is the result of a successful map lookup (meaning that
                    123:  *     the maps are locked by the caller)
                    124:  * => we may unlock the maps if needed (for I/O)
                    125:  * => we put our output result in "output"
                    126:  * => we return the number of pages we loaned, or -1 if we had an error
                    127:  */
                    128:
                    129: static __inline int
                    130: uvm_loanentry(ufi, output, flags)
                    131:        struct uvm_faultinfo *ufi;
                    132:        void ***output;
                    133:        int flags;
                    134: {
                    135:        vaddr_t curaddr = ufi->orig_rvaddr;
                    136:        vsize_t togo = ufi->size;
                    137:        struct vm_aref *aref = &ufi->entry->aref;
                    138:        struct uvm_object *uobj = ufi->entry->object.uvm_obj;
                    139:        struct vm_anon *anon;
                    140:        int rv, result = 0;
                    141:
                    142:        /*
                    143:         * lock us the rest of the way down
                    144:         */
                    145:        if (uobj)
                    146:                simple_lock(&uobj->vmobjlock);
                    147:
                    148:        /*
                    149:         * loop until done
                    150:         */
                    151:        while (togo) {
                    152:
                    153:                /*
                    154:                 * find the page we want.   check the anon layer first.
                    155:                 */
                    156:
                    157:                if (aref->ar_amap) {
                    158:                        anon = amap_lookup(aref, curaddr - ufi->entry->start);
                    159:                } else {
                    160:                        anon = NULL;
                    161:                }
                    162:
                    163:                if (anon) {
                    164:                        rv = uvm_loananon(ufi, output, flags, anon);
                    165:                } else if (uobj) {
                    166:                        rv = uvm_loanuobj(ufi, output, flags, curaddr);
                    167:                } else if (UVM_ET_ISCOPYONWRITE(ufi->entry)) {
                    168:                        rv = uvm_loanzero(ufi, output, flags);
                    169:                } else {
                    170:                        rv = -1;                /* null map entry... fail now */
                    171:                }
                    172:
                    173:                /* total failure */
                    174:                if (rv < 0)
                    175:                        return(-1);
                    176:
                    177:                /* relock failed, need to do another lookup */
                    178:                if (rv == 0)
                    179:                        return(result);
                    180:
                    181:                /*
                    182:                 * got it... advance to next page
                    183:                 */
                    184:                result++;
                    185:                togo -= PAGE_SIZE;
                    186:                curaddr += PAGE_SIZE;
                    187:        }
                    188:
                    189:        /*
                    190:         * unlock everything and return
                    191:         */
                    192:        uvmfault_unlockall(ufi, aref->ar_amap, uobj, NULL);
                    193:        return(result);
                    194: }
                    195:
                    196: /*
                    197:  * normal functions
                    198:  */
                    199:
                    200: /*
                    201:  * uvm_loan: loan pages out to anons or to the kernel
                    202:  *
                    203:  * => map should be unlocked
                    204:  * => start and len should be multiples of PAGE_SIZE
                    205:  * => result is either an array of anon's or vm_pages (depending on flags)
                    206:  * => flag values: UVM_LOAN_TOANON - loan to anons
                    207:  *                 UVM_LOAN_TOPAGE - loan to wired kernel page
                    208:  *    one and only one of these flags must be set!
                    209:  */
                    210:
                    211: int
                    212: uvm_loan(map, start, len, result, flags)
                    213:        struct vm_map *map;
                    214:        vaddr_t start;
                    215:        vsize_t len;
                    216:        void **result;
                    217:        int flags;
                    218: {
                    219:        struct uvm_faultinfo ufi;
                    220:        void **output;
                    221:        int rv;
                    222:
                    223: #ifdef DIAGNOSTIC
                    224:        if (map->flags & VM_MAP_INTRSAFE)
                    225:                panic("uvm_loan: intrsafe map");
                    226: #endif
                    227:
                    228:        /*
                    229:         * ensure that one and only one of the flags is set
                    230:         */
                    231:
                    232:        if ((flags & (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE)) ==
                    233:            (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE) ||
                    234:            (flags & (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE)) == 0)
                    235:                return (EFAULT);
                    236:
                    237:        /*
                    238:         * "output" is a pointer to the current place to put the loaned
                    239:         * page...
                    240:         */
                    241:
                    242:        output = &result[0];    /* start at the beginning ... */
                    243:
                    244:        /*
                    245:         * while we've got pages to do
                    246:         */
                    247:
                    248:        while (len > 0) {
                    249:
                    250:                /*
                    251:                 * fill in params for a call to uvmfault_lookup
                    252:                 */
                    253:
                    254:                ufi.orig_map = map;
                    255:                ufi.orig_rvaddr = start;
                    256:                ufi.orig_size = len;
                    257:
                    258:                /*
                    259:                 * do the lookup, the only time this will fail is if we hit on
                    260:                 * an unmapped region (an error)
                    261:                 */
                    262:
                    263:                if (!uvmfault_lookup(&ufi, FALSE))
                    264:                        goto fail;
                    265:
                    266:                /*
                    267:                 * map now locked.  now do the loanout...
                    268:                 */
                    269:                rv = uvm_loanentry(&ufi, &output, flags);
                    270:                if (rv < 0)
                    271:                        goto fail;
                    272:
                    273:                /*
                    274:                 * done!  the map is unlocked.  advance, if possible.
                    275:                 *
                    276:                 * XXXCDC: could be recoded to hold the map lock with
                    277:                 *         smarter code (but it only happens on map entry
                    278:                 *         boundaries, so it isn't that bad).
                    279:                 */
                    280:                if (rv) {
                    281:                        rv <<= PAGE_SHIFT;
                    282:                        len -= rv;
                    283:                        start += rv;
                    284:                }
                    285:        }
                    286:
                    287:        /*
                    288:         * got it!   return success.
                    289:         */
                    290:
                    291:        return (0);
                    292:
                    293: fail:
                    294:        /*
                    295:         * fail: failed to do it.   drop our loans and return failure code.
                    296:         */
                    297:        if (output - result) {
                    298:                if (flags & UVM_LOAN_TOANON)
                    299:                        uvm_unloananon((struct vm_anon **)result,
                    300:                            output - result);
                    301:                else
                    302:                        uvm_unloanpage((struct vm_page **)result,
                    303:                            output - result);
                    304:        }
                    305:        return (EFAULT);
                    306: }
                    307:
                    308: /*
                    309:  * uvm_loananon: loan a page from an anon out
                    310:  *
                    311:  * => return value:
                    312:  *     -1 = fatal error, everything is unlocked, abort.
                    313:  *      0 = lookup in ufi went stale, everything unlocked, relookup and
                    314:  *             try again
                    315:  *      1 = got it, everything still locked
                    316:  */
                    317:
                    318: int
                    319: uvm_loananon(ufi, output, flags, anon)
                    320:        struct uvm_faultinfo *ufi;
                    321:        void ***output;
                    322:        int flags;
                    323:        struct vm_anon *anon;
                    324: {
                    325:        struct vm_page *pg;
                    326:        int result;
                    327:
                    328:        /*
                    329:         * if we are loaning to another anon then it is easy, we just
                    330:         * bump the reference count on the current anon and return a
                    331:         * pointer to it.
                    332:         */
                    333:        if (flags & UVM_LOAN_TOANON) {
                    334:                simple_lock(&anon->an_lock);
                    335:                pg = anon->an_page;
                    336:                if (pg && (pg->pg_flags & PQ_ANON) != 0 && anon->an_ref == 1)
                    337:                        /* read protect it */
                    338:                        pmap_page_protect(pg, VM_PROT_READ);
                    339:                anon->an_ref++;
                    340:                **output = anon;
                    341:                *output = (*output) + 1;
                    342:                simple_unlock(&anon->an_lock);
                    343:                return(1);
                    344:        }
                    345:
                    346:        /*
                    347:         * we are loaning to a kernel-page.   we need to get the page
                    348:         * resident so we can wire it.   uvmfault_anonget will handle
                    349:         * this for us.
                    350:         */
                    351:
                    352:        simple_lock(&anon->an_lock);
                    353:        result = uvmfault_anonget(ufi, ufi->entry->aref.ar_amap, anon);
                    354:
                    355:        /*
                    356:         * if we were unable to get the anon, then uvmfault_anonget has
                    357:         * unlocked everything and returned an error code.
                    358:         */
                    359:
                    360:        if (result != VM_PAGER_OK) {
                    361:
                    362:                /* need to refault (i.e. refresh our lookup) ? */
                    363:                if (result == VM_PAGER_REFAULT)
                    364:                        return(0);
                    365:
                    366:                /* "try again"?   sleep a bit and retry ... */
                    367:                if (result == VM_PAGER_AGAIN) {
                    368:                        tsleep((caddr_t)&lbolt, PVM, "loanagain", 0);
                    369:                        return(0);
                    370:                }
                    371:
                    372:                /* otherwise flag it as an error */
                    373:                return(-1);
                    374:        }
                    375:
                    376:        /*
                    377:         * we have the page and its owner locked: do the loan now.
                    378:         */
                    379:
                    380:        pg = anon->an_page;
                    381:        uvm_lock_pageq();
                    382:        if (pg->loan_count == 0)
                    383:                pmap_page_protect(pg, VM_PROT_READ);
                    384:        pg->loan_count++;
                    385:        uvm_pagewire(pg);       /* always wire it */
                    386:        uvm_unlock_pageq();
                    387:        **output = pg;
                    388:        *output = (*output) + 1;
                    389:
                    390:        /* unlock anon and return success */
                    391:        if (pg->uobject)
                    392:                simple_unlock(&pg->uobject->vmobjlock);
                    393:        simple_unlock(&anon->an_lock);
                    394:        return(1);
                    395: }
                    396:
                    397: /*
                    398:  * uvm_loanuobj: loan a page from a uobj out
                    399:  *
                    400:  * => return value:
                    401:  *     -1 = fatal error, everything is unlocked, abort.
                    402:  *      0 = lookup in ufi went stale, everything unlocked, relookup and
                    403:  *             try again
                    404:  *      1 = got it, everything still locked
                    405:  */
                    406:
                    407: int
                    408: uvm_loanuobj(ufi, output, flags, va)
                    409:        struct uvm_faultinfo *ufi;
                    410:        void ***output;
                    411:        int flags;
                    412:        vaddr_t va;
                    413: {
                    414:        struct vm_amap *amap = ufi->entry->aref.ar_amap;
                    415:        struct uvm_object *uobj = ufi->entry->object.uvm_obj;
                    416:        struct vm_page *pg;
                    417:        struct vm_anon *anon;
                    418:        int result, npages;
                    419:        boolean_t locked;
                    420:
                    421:        /*
                    422:         * first we must make sure the page is resident.
                    423:         *
                    424:         * XXXCDC: duplicate code with uvm_fault().
                    425:         */
                    426:
                    427:        if (uobj->pgops->pgo_get) {
                    428:                npages = 1;
                    429:                pg = NULL;
                    430:                result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,
                    431:                    &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_LOCKED);
                    432:        } else {
                    433:                result = VM_PAGER_ERROR;
                    434:        }
                    435:
                    436:        /*
                    437:         * check the result of the locked pgo_get.  if there is a problem,
                    438:         * then we fail the loan.
                    439:         */
                    440:
                    441:        if (result != VM_PAGER_OK && result != VM_PAGER_UNLOCK) {
                    442:                uvmfault_unlockall(ufi, amap, uobj, NULL);
                    443:                return(-1);
                    444:        }
                    445:
                    446:        /*
                    447:         * if we need to unlock for I/O, do so now.
                    448:         */
                    449:
                    450:        if (result == VM_PAGER_UNLOCK) {
                    451:                uvmfault_unlockall(ufi, amap, NULL, NULL);
                    452:
                    453:                npages = 1;
                    454:                /* locked: uobj */
                    455:                result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,
                    456:                    &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, 0);
                    457:                /* locked: <nothing> */
                    458:
                    459:                /*
                    460:                 * check for errors
                    461:                 */
                    462:
                    463:                if (result != VM_PAGER_OK) {
                    464:                         if (result == VM_PAGER_AGAIN) {
                    465:                                tsleep((caddr_t)&lbolt, PVM, "fltagain2", 0);
                    466:                                return(0); /* redo the lookup and try again */
                    467:                        }
                    468:                        return(-1);     /* total failure */
                    469:                }
                    470:
                    471:                /*
                    472:                 * pgo_get was a success.   attempt to relock everything.
                    473:                 */
                    474:
                    475:                locked = uvmfault_relock(ufi);
                    476:                simple_lock(&uobj->vmobjlock);
                    477:
                    478:                /*
                    479:                 * verify that the page has not be released and re-verify
                    480:                 * that amap slot is still free.   if there is a problem we
                    481:                 * drop our lock (thus force a lookup refresh/retry).
                    482:                 */
                    483:
                    484:                if ((pg->pg_flags & PG_RELEASED) != 0 ||
                    485:                    (locked && amap && amap_lookup(&ufi->entry->aref,
                    486:                    ufi->orig_rvaddr - ufi->entry->start))) {
                    487:
                    488:                        if (locked)
                    489:                                uvmfault_unlockall(ufi, amap, NULL, NULL);
                    490:                        locked = FALSE;
                    491:                }
                    492:
                    493:                /*
                    494:                 * didn't get the lock?   release the page and retry.
                    495:                 */
                    496:
                    497:                if (locked == FALSE) {
                    498:
                    499:                        if (pg->pg_flags & PG_WANTED)
                    500:                                /* still holding object lock */
                    501:                                wakeup(pg);
                    502:
                    503:                        if (pg->pg_flags & PG_RELEASED) {
                    504: #ifdef DIAGNOSTIC
                    505:                                if (uobj->pgops->pgo_releasepg == NULL)
                    506:                        panic("uvm_loanuobj: object has no releasepg function");
                    507: #endif
                    508:                                /* frees page */
                    509:                                if (uobj->pgops->pgo_releasepg(pg, NULL))
                    510:                                        simple_unlock(&uobj->vmobjlock);
                    511:                                return (0);
                    512:                        }
                    513:
                    514:                        uvm_lock_pageq();
                    515:                        uvm_pageactivate(pg); /* make sure it is in queues */
                    516:                        uvm_unlock_pageq();
                    517:                        atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_WANTED);
                    518:                        UVM_PAGE_OWN(pg, NULL);
                    519:                        simple_unlock(&uobj->vmobjlock);
                    520:                        return (0);
                    521:                }
                    522:        }
                    523:
                    524:        /*
                    525:         * at this point we have the page we want ("pg") marked PG_BUSY for us
                    526:         * and we have all data structures locked.   do the loanout.   page can
                    527:         * not be PG_RELEASED (we caught this above).
                    528:         */
                    529:
                    530:        if ((flags & UVM_LOAN_TOANON) == 0) {   /* loan to wired-kernel page? */
                    531:                uvm_lock_pageq();
                    532:                if (pg->loan_count == 0)
                    533:                        pmap_page_protect(pg, VM_PROT_READ);
                    534:                pg->loan_count++;
                    535:                uvm_pagewire(pg);
                    536:                uvm_unlock_pageq();
                    537:                **output = pg;
                    538:                *output = (*output) + 1;
                    539:                if (pg->pg_flags & PG_WANTED)
                    540:                        wakeup(pg);
                    541:                atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
                    542:                UVM_PAGE_OWN(pg, NULL);
                    543:                return(1);              /* got it! */
                    544:        }
                    545:
                    546:        /*
                    547:         * must be a loan to an anon.   check to see if there is already
                    548:         * an anon associated with this page.  if so, then just return
                    549:         * a reference to this object.   the page should already be
                    550:         * mapped read-only because it is already on loan.
                    551:         */
                    552:
                    553:        if (pg->uanon) {
                    554:                anon = pg->uanon;
                    555:                simple_lock(&anon->an_lock);
                    556:                anon->an_ref++;
                    557:                simple_unlock(&anon->an_lock);
                    558:                **output = anon;
                    559:                *output = (*output) + 1;
                    560:                uvm_lock_pageq();
                    561:                uvm_pageactivate(pg);   /* reactivate */
                    562:                uvm_unlock_pageq();
                    563:                if (pg->pg_flags & PG_WANTED)
                    564:                        wakeup(pg);
                    565:                atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
                    566:                UVM_PAGE_OWN(pg, NULL);
                    567:                return(1);
                    568:        }
                    569:
                    570:        /*
                    571:         * need to allocate a new anon
                    572:         */
                    573:
                    574:        anon = uvm_analloc();
                    575:        if (anon == NULL) {             /* out of VM! */
                    576:                if (pg->pg_flags & PG_WANTED)
                    577:                        wakeup(pg);
                    578:                atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
                    579:                UVM_PAGE_OWN(pg, NULL);
                    580:                uvmfault_unlockall(ufi, amap, uobj, NULL);
                    581:                return(-1);
                    582:        }
                    583:        anon->an_page = pg;
                    584:        pg->uanon = anon;
                    585:        uvm_lock_pageq();
                    586:        if (pg->loan_count == 0)
                    587:                pmap_page_protect(pg, VM_PROT_READ);
                    588:        pg->loan_count++;
                    589:        uvm_pageactivate(pg);
                    590:        uvm_unlock_pageq();
                    591:        **output = anon;
                    592:        *output = (*output) + 1;
                    593:        if (pg->pg_flags & PG_WANTED)
                    594:                wakeup(pg);
                    595:        atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
                    596:        UVM_PAGE_OWN(pg, NULL);
                    597:        return(1);
                    598: }
                    599:
                    600: /*
                    601:  * uvm_loanzero: "loan" a zero-fill page out
                    602:  *
                    603:  * => return value:
                    604:  *     -1 = fatal error, everything is unlocked, abort.
                    605:  *      0 = lookup in ufi went stale, everything unlocked, relookup and
                    606:  *             try again
                    607:  *      1 = got it, everything still locked
                    608:  */
                    609:
                    610: int
                    611: uvm_loanzero(ufi, output, flags)
                    612:        struct uvm_faultinfo *ufi;
                    613:        void ***output;
                    614:        int flags;
                    615: {
                    616:        struct vm_anon *anon;
                    617:        struct vm_page *pg;
                    618:
                    619:        if ((flags & UVM_LOAN_TOANON) == 0) {   /* loaning to kernel-page */
                    620:
                    621:                while ((pg = uvm_pagealloc(NULL, 0, NULL,
                    622:                    UVM_PGA_ZERO)) == NULL) {
                    623:                        uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap,
                    624:                            ufi->entry->object.uvm_obj, NULL);
                    625:                        uvm_wait("loanzero1");
                    626:                        if (!uvmfault_relock(ufi))
                    627:                                return(0);
                    628:                        if (ufi->entry->object.uvm_obj)
                    629:                                simple_lock(
                    630:                                    &ufi->entry->object.uvm_obj->vmobjlock);
                    631:                        /* ... and try again */
                    632:                }
                    633:
                    634:                /* got a zero'd page; return */
                    635:                atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
                    636:                UVM_PAGE_OWN(pg, NULL);
                    637:                **output = pg;
                    638:                *output = (*output) + 1;
                    639:                uvm_lock_pageq();
                    640:                /* wire it as we are loaning to kernel-page */
                    641:                uvm_pagewire(pg);
                    642:                pg->loan_count = 1;
                    643:                uvm_unlock_pageq();
                    644:                return(1);
                    645:        }
                    646:
                    647:        /* loaning to an anon */
                    648:        while ((anon = uvm_analloc()) == NULL ||
                    649:            (pg = uvm_pagealloc(NULL, 0, anon, UVM_PGA_ZERO)) == NULL) {
                    650:
                    651:                /* unlock everything */
                    652:                uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap,
                    653:                       ufi->entry->object.uvm_obj, NULL);
                    654:
                    655:                /* out of swap causes us to fail */
                    656:                if (anon == NULL)
                    657:                        return(-1);
                    658:
                    659:                uvm_anfree(anon);
                    660:                uvm_wait("loanzero2");          /* wait for pagedaemon */
                    661:
                    662:                if (!uvmfault_relock(ufi))
                    663:                        /* map changed while unlocked, need relookup */
                    664:                        return (0);
                    665:
                    666:                /* relock everything else */
                    667:                if (ufi->entry->object.uvm_obj)
                    668:                        simple_lock(&ufi->entry->object.uvm_obj->vmobjlock);
                    669:                /* ... and try again */
                    670:        }
                    671:
                    672:        /* got a zero'd page; return */
                    673:        atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
                    674:        UVM_PAGE_OWN(pg, NULL);
                    675:        uvm_lock_pageq();
                    676:        uvm_pageactivate(pg);
                    677:        uvm_unlock_pageq();
                    678:        **output = anon;
                    679:        *output = (*output) + 1;
                    680:        return(1);
                    681: }
                    682:
                    683:
                    684: /*
                    685:  * uvm_unloananon: kill loans on anons (basically a normal ref drop)
                    686:  *
                    687:  * => we expect all our resources to be unlocked
                    688:  */
                    689:
                    690: void
                    691: uvm_unloananon(aloans, nanons)
                    692:        struct vm_anon **aloans;
                    693:        int nanons;
                    694: {
                    695:        struct vm_anon *anon;
                    696:
                    697:        while (nanons-- > 0) {
                    698:                int refs;
                    699:
                    700:                anon = *aloans++;
                    701:                simple_lock(&anon->an_lock);
                    702:                refs = --anon->an_ref;
                    703:                simple_unlock(&anon->an_lock);
                    704:
                    705:                if (refs == 0) {
                    706:                        uvm_anfree(anon);       /* last reference: kill anon */
                    707:                }
                    708:        }
                    709: }
                    710:
                    711: /*
                    712:  * uvm_unloanpage: kill loans on pages loaned out to the kernel
                    713:  *
                    714:  * => we expect all our resources to be unlocked
                    715:  */
                    716:
                    717: void
                    718: uvm_unloanpage(ploans, npages)
                    719:        struct vm_page **ploans;
                    720:        int npages;
                    721: {
                    722:        struct vm_page *pg;
                    723:
                    724:        uvm_lock_pageq();
                    725:
                    726:        while (npages-- > 0) {
                    727:                pg = *ploans++;
                    728:
                    729:                if (pg->loan_count < 1)
                    730:                        panic("uvm_unloanpage: page %p isn't loaned", pg);
                    731:
                    732:                pg->loan_count--;               /* drop loan */
                    733:                uvm_pageunwire(pg);             /* and wire */
                    734:
                    735:                /*
                    736:                 * if page is unowned and we killed last loan, then we can
                    737:                 * free it
                    738:                 */
                    739:                if (pg->loan_count == 0 && pg->uobject == NULL &&
                    740:                    pg->uanon == NULL) {
                    741:
                    742:                        if (pg->pg_flags & PG_BUSY)
                    743:        panic("uvm_unloanpage: page %p unowned but PG_BUSY!", pg);
                    744:
                    745:                        /* be safe */
                    746:                        pmap_page_protect(pg, VM_PROT_NONE);
                    747:                        uvm_pagefree(pg);       /* pageq locked above */
                    748:
                    749:                }
                    750:        }
                    751:
                    752:        uvm_unlock_pageq();
                    753: }
                    754:

CVSweb