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

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

1.1       nbrk        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: }

CVSweb