Annotation of 43BSDReno/sys/kern/vm_mem.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)vm_mem.c    7.15 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "cmap.h"
                     26: #include "user.h"
                     27: #include "proc.h"
                     28: #include "text.h"
                     29: #include "vm.h"
                     30: #include "buf.h"
                     31: #include "vnode.h"
                     32: #include "mount.h"
                     33: #include "trace.h"
                     34: 
                     35: #include "machine/pte.h"
                     36: 
                     37: /*
                     38:  * Allocate memory, and always succeed
                     39:  * by jolting page-out daemon
                     40:  * so as to obtain page frames.
                     41:  * To be used in conjunction with vmemfree().
                     42:  */
                     43: vmemall(pte, size, p, type)
                     44:        register struct pte *pte;
                     45:        int size;
                     46:        struct proc *p;
                     47: {
                     48:        register int m;
                     49: 
                     50:        if (size <= 0 || size > maxmem)
                     51:                panic("vmemall size");
                     52:        while (size > 0) {
                     53:                if (freemem < desfree)
                     54:                        outofmem();
                     55:                while (freemem == 0)
                     56:                        sleep((caddr_t)&freemem, PSWP+2);
                     57:                m = imin(size, freemem);
                     58:                (void) memall(pte, m, p, type);
                     59:                size -= m;
                     60:                pte += m;
                     61:        }
                     62:        if (freemem < desfree)
                     63:                outofmem();
                     64:        /*
                     65:         * Always succeeds, but return success for
                     66:         * vgetu and vgetpt (e.g.) which call either
                     67:         * memall or vmemall depending on context.
                     68:         */
                     69:        return (1);
                     70: }
                     71: 
                     72: /*
                     73:  * Free valid and reclaimable page frames belonging to the
                     74:  * count pages starting at pte.  If a page is valid
                     75:  * or reclaimable and locked (but not a system page), then
                     76:  * we simply mark the page as c_gone and let the pageout
                     77:  * daemon free the page when it is through with it.
                     78:  * If a page is reclaimable, and already in the free list, then
                     79:  * we mark the page as c_gone, and (of course) don't free it.
                     80:  *
                     81:  * Determines the largest contiguous cluster of
                     82:  * valid pages and frees them in one call to memfree.
                     83:  */
                     84: vmemfree(pte, count)
                     85:        register struct pte *pte;
                     86:        register int count;
                     87: {
                     88:        register struct cmap *c;
                     89:        register struct pte *spte;
                     90:        register int j;
                     91:        int size, pcnt;
                     92: #ifdef notdef
                     93:        int fileno;
                     94: #endif
                     95: 
                     96:        if (count % CLSIZE)
                     97:                panic("vmemfree");
                     98:        for (size = 0, pcnt = 0; count > 0; pte += CLSIZE, count -= CLSIZE) {
                     99:                if (pte->pg_fod == 0 && pte->pg_pfnum) {
                    100:                        c = &cmap[pgtocm(pte->pg_pfnum)];
                    101:                        pcnt += CLSIZE;
                    102:                        if (c->c_lock && c->c_type != CSYS) {
                    103:                                for (j = 0; j < CLSIZE; j++)
                    104:                                        *(int *)(pte+j) &= PG_PROT;
                    105:                                c->c_gone = 1;
                    106:                                goto free;
                    107:                        }
                    108:                        if (c->c_free) {
                    109:                                pcnt -= CLSIZE;
                    110:                                for (j = 0; j < CLSIZE; j++)
                    111:                                        *(int *)(pte+j) &= PG_PROT;
                    112:                                if (c->c_type == CTEXT)
                    113:                                        distpte(&text[c->c_ndx], c->c_page,
                    114:                                            pte);
                    115:                                c->c_gone = 1;
                    116:                                goto free;
                    117:                        }
                    118:                        if (size == 0)
                    119:                                spte = pte;
                    120:                        size += CLSIZE;
                    121:                        continue;
                    122:                }
                    123: #ifdef notdef
                    124:                /* Don't do anything with mapped ptes */
                    125:                if (pte->pg_fod && pte->pg_v)
                    126:                        goto free;
                    127: #endif
                    128:                if (pte->pg_fod) {
                    129: #ifdef notdef
                    130:                        fileno = ((struct fpte *)pte)->pg_fileno;
                    131:                        if (fileno < NOFILE)
                    132:                                panic("vmemfree vread");
                    133: #endif
                    134:                        for (j = 0; j < CLSIZE; j++)
                    135:                                *(int *)(pte+j) &= PG_PROT;
                    136:                }
                    137: free:
                    138:                if (size) {
                    139:                        memfree(spte, size, 1);
                    140:                        size = 0;
                    141:                }
                    142:        }
                    143:        if (size)
                    144:                memfree(spte, size, 1);
                    145:        return (pcnt);
                    146: }
                    147: 
                    148: /*
                    149:  * Unlink a page frame from the free list -
                    150:  *
                    151:  * Performed if the page being reclaimed
                    152:  * is in the free list.
                    153:  */
                    154: munlink(c)
                    155:        register struct cmap *c;
                    156: {
                    157:        register int next, prev;
                    158: 
                    159:        next = c->c_next;
                    160:        prev = c->c_prev;
                    161:        cmap[prev].c_next = next;
                    162:        cmap[next].c_prev = prev;
                    163:        c->c_free = 0;
                    164:        if (freemem < minfree)
                    165:                outofmem();
                    166:        freemem -= CLSIZE;
                    167: }
                    168: 
                    169: /*
                    170:  * Allocate memory -
                    171:  *
                    172:  * The free list appears as a doubly linked list
                    173:  * in the core map with cmap[0] serving as a header.
                    174:  */
                    175: memall(pte, size, p, type)
                    176:        register struct pte *pte;
                    177:        int size;
                    178:        struct proc *p;
                    179: {
                    180:        register struct cmap *c;
                    181:        register struct pte *rpte;
                    182:        register struct proc *rp;
                    183:        int i, j, next, curpos;
                    184:        unsigned pf;
                    185:        struct cmap *c1, *c2;
                    186:        int s;
                    187: 
                    188:        if (size % CLSIZE)
                    189:                panic("memall");
                    190:        s = splimp();
                    191:        if (size > freemem) {
                    192:                splx(s);
                    193:                return (0);
                    194:        }
                    195:        trace(TR_MALL, size, u.u_procp->p_pid);
                    196:        for (i = size; i > 0; i -= CLSIZE) {
                    197:                curpos = cmap[CMHEAD].c_next;
                    198:                c = &cmap[curpos];
                    199:                freemem -= CLSIZE;
                    200:                next = c->c_next;
                    201:                cmap[CMHEAD].c_next = next;
                    202:                cmap[next].c_prev = CMHEAD;
                    203:                if (c->c_free == 0)
                    204:                        panic("dup mem alloc");
                    205:                if (cmtopg(curpos) > maxfree)
                    206:                        panic("bad mem alloc");
                    207:                if (c->c_gone == 0 && c->c_type != CSYS) {
                    208:                        if (c->c_type == CTEXT)
                    209:                                rp = text[c->c_ndx].x_caddr;
                    210:                        else
                    211:                                rp = &proc[c->c_ndx];
                    212:                        while (rp->p_flag & SNOVM)
                    213:                                rp = rp->p_xlink;
                    214:                        switch (c->c_type) {
                    215: 
                    216:                        case CTEXT:
                    217:                                rpte = tptopte(rp, c->c_page);
                    218:                                break;
                    219: 
                    220:                        case CDATA:
                    221:                                rpte = dptopte(rp, c->c_page);
                    222:                                break;
                    223: 
                    224:                        case CSTACK:
                    225:                                rpte = sptopte(rp, c->c_page);
                    226:                                break;
                    227:                        }
                    228:                        zapcl(rpte, pg_pfnum) = 0;
                    229:                        if (c->c_type == CTEXT)
                    230:                                distpte(&text[c->c_ndx], c->c_page, rpte);
                    231:                }
                    232:                switch (type) {
                    233: 
                    234:                case CSYS:
                    235:                        c->c_ndx = p->p_ndx;
                    236:                        break;
                    237: 
                    238:                case CTEXT:
                    239:                        c->c_page = vtotp(p, ptetov(p, pte));
                    240:                        c->c_ndx = p->p_textp - &text[0];
                    241:                        break;
                    242: 
                    243:                case CDATA:
                    244:                        c->c_page = vtodp(p, ptetov(p, pte));
                    245:                        c->c_ndx = p->p_ndx;
                    246:                        break;
                    247: 
                    248:                case CSTACK:
                    249:                        c->c_page = vtosp(p, ptetov(p, pte));
                    250:                        c->c_ndx = p->p_ndx;
                    251:                        break;
                    252:                }
                    253:                if (c->c_blkno) {
                    254:                        /*
                    255:                         * This is very like munhash(), except
                    256:                         * that we really don't want to bother
                    257:                         * to calculate a vp to pass to it.
                    258:                         */
                    259:                        j = CMHASH(c->c_blkno);
                    260:                        c1 = &cmap[cmhash[j]];
                    261:                        if (c1 == c)
                    262:                                cmhash[j] = c1->c_hlink;
                    263:                        else {
                    264:                                for (;;) {
                    265:                                        if (c1 == ecmap)
                    266:                                                panic("memall ecmap");
                    267:                                        c2 = c1;
                    268:                                        c1 = &cmap[c2->c_hlink];
                    269:                                        if (c1 == c)
                    270:                                                break;
                    271:                                }
                    272:                                c2->c_hlink = c1->c_hlink;
                    273:                        }
                    274:                        if (mfind(c->c_vp, (daddr_t)(u_long)c->c_blkno))
                    275:                                panic("memall mfind");
                    276:                        HOLDRELE(c1->c_vp);
                    277:                        c1->c_vp = NULLVP;
                    278:                        c1->c_blkno = 0;
                    279:                        c1->c_hlink = 0;
                    280:                }
                    281:                pf = cmtopg(curpos);
                    282:                for (j = 0; j < CLSIZE; j++) {
                    283:                        *(int *)pte = 0;
                    284:                        pte++->pg_pfnum = pf++;
                    285:                }
                    286:                c->c_free = 0;
                    287:                c->c_gone = 0;
                    288:                if (c->c_intrans || c->c_want)
                    289:                        panic("memall intrans|want");
                    290:                c->c_lock = 1;
                    291:                c->c_type = type;
                    292:        }
                    293:        splx(s);
                    294:        return (size);
                    295: }
                    296: 
                    297: /*
                    298:  * Free memory -
                    299:  *
                    300:  * The page frames being returned are inserted
                    301:  * to the head/tail of the free list depending
                    302:  * on whether there is any possible future use of them.
                    303:  *
                    304:  * If the freemem count had been zero,
                    305:  * the processes sleeping for memory
                    306:  * are awakened.
                    307:  */
                    308: memfree(pte, size, detach)
                    309:        register struct pte *pte;
                    310:        register int size;
                    311: {
                    312:        register int i, j, prev, next;
                    313:        register struct cmap *c;
                    314:        int s;
                    315:        
                    316:        if (size % CLSIZE)
                    317:                panic("memfree");
                    318:        if (freemem < CLSIZE * KLMAX)
                    319:                wakeup((caddr_t)&freemem);
                    320:        while (size > 0) {
                    321:                size -= CLSIZE;
                    322:                i = pte->pg_pfnum;
                    323:                if (i < firstfree || i > maxfree)
                    324:                        panic("bad mem free");
                    325:                i = pgtocm(i);
                    326:                c = &cmap[i];
                    327:                if (c->c_free)
                    328:                        panic("dup mem free");
                    329:                if (detach && c->c_type != CSYS) {
                    330:                        for (j = 0; j < CLSIZE; j++)
                    331:                                *(int *)(pte+j) &= PG_PROT;
                    332:                        c->c_gone = 1;
                    333:                }
                    334:                s = splimp();
                    335:                if (detach && c->c_blkno == 0) {
                    336:                        next = cmap[CMHEAD].c_next;
                    337:                        cmap[next].c_prev = i;
                    338:                        c->c_prev = CMHEAD;
                    339:                        c->c_next = next;
                    340:                        cmap[CMHEAD].c_next = i;
                    341:                } else {
                    342:                        prev = cmap[CMHEAD].c_prev;
                    343:                        cmap[prev].c_next = i;
                    344:                        c->c_next = CMHEAD;
                    345:                        c->c_prev = prev;
                    346:                        cmap[CMHEAD].c_prev = i;
                    347:                }
                    348:                c->c_free = 1;
                    349:                freemem += CLSIZE;
                    350:                splx(s);
                    351:                pte += CLSIZE;
                    352:        }
                    353: }
                    354: 
                    355: /*
                    356:  * Enter clist block c on the hash chains.
                    357:  * It contains file system block bn from vnode vp.
                    358:  */
                    359: mhash(c, vp, bn)
                    360:        register struct cmap *c;
                    361:        struct vnode *vp;
                    362:        daddr_t bn;
                    363: {
                    364:        register int i = CMHASH(bn);
                    365: 
                    366:        c->c_hlink = cmhash[i];
                    367:        cmhash[i] = c - cmap;
                    368:        c->c_blkno = bn;
                    369:        c->c_vp = vp;
                    370:        VHOLD(vp);
                    371: }
                    372: 
                    373: /*
                    374:  * Pull the clist entry of <vp,bn> off the hash chains
                    375:  * if present.
                    376:  */
                    377: munhash(vp, bn)
                    378:        struct vnode *vp;
                    379:        daddr_t bn;
                    380: {
                    381:        int i = CMHASH(bn);
                    382:        register struct cmap *c1, *c2;
                    383:        int s = splimp();
                    384: 
                    385:        c1 = &cmap[cmhash[i]];
                    386:        if (c1 == ecmap)
                    387:                goto out;
                    388:        if (c1->c_blkno == bn && c1->c_vp == vp)
                    389:                cmhash[i] = c1->c_hlink;
                    390:        else {
                    391:                for (;;) {
                    392:                        c2 = c1;
                    393:                        c1 = &cmap[c2->c_hlink];
                    394:                        if (c1 == ecmap)
                    395:                                goto out;
                    396:                        if (c1->c_blkno == bn && c1->c_vp == vp)
                    397:                                break;
                    398:                }
                    399:                c2->c_hlink = c1->c_hlink;
                    400:        }
                    401:        HOLDRELE(vp);
                    402:        c1->c_vp = NULLVP;
                    403:        c1->c_blkno = 0;
                    404:        c1->c_hlink = 0;
                    405: out:
                    406:        splx(s);
                    407: }
                    408: 
                    409: /*
                    410:  * Look for block bn of vnode vp in the free pool.
                    411:  * Currently it should not be possible to find it unless it is
                    412:  * c_free and c_gone, although this may later not be true.
                    413:  * (This is because active texts are locked against file system
                    414:  * writes by the system.)
                    415:  */
                    416: struct cmap *
                    417: mfind(vp, bn)
                    418:        struct vnode *vp;
                    419:        daddr_t bn;
                    420: {
                    421:        register struct cmap *c1 = &cmap[cmhash[CMHASH(bn)]];
                    422:        int si = splimp();
                    423: 
                    424:        while (c1 != ecmap) {
                    425:                if (c1->c_blkno == bn && c1->c_vp == vp) {
                    426:                        splx(si);
                    427:                        return (c1);
                    428:                }
                    429:                c1 = &cmap[c1->c_hlink];
                    430:        }
                    431:        splx(si);
                    432:        return ((struct cmap *)0);
                    433: }
                    434: 
                    435: /*
                    436:  * Purge blocks from vnode vp from incore cache
                    437:  * before umount().
                    438:  */
                    439: mpurge(vp)
                    440:        struct vnode *vp;
                    441: {
                    442:        register struct cmap *c1, *c2;
                    443:        register int i;
                    444:        int relcnt = 0, si = splimp();
                    445: 
                    446:        for (i = 0; i < CMHSIZ; i++) {
                    447: more:
                    448:                c1 = &cmap[cmhash[i]];
                    449:                if (c1 == ecmap)
                    450:                        continue;
                    451:                if (c1->c_vp == vp)
                    452:                        cmhash[i] = c1->c_hlink;
                    453:                else {
                    454:                        for (;;) {
                    455:                                c2 = c1;
                    456:                                c1 = &cmap[c1->c_hlink];
                    457:                                if (c1 == ecmap)
                    458:                                        goto cont;
                    459:                                if (c1->c_vp == vp)
                    460:                                        break;
                    461:                        }
                    462:                        c2->c_hlink = c1->c_hlink;
                    463:                }
                    464:                relcnt++;
                    465:                c1->c_vp = NULLVP;
                    466:                c1->c_blkno = 0;
                    467:                c1->c_hlink = 0;
                    468:                goto more;
                    469: cont:
                    470:                ;
                    471:        }
                    472:        while (relcnt--)
                    473:                HOLDRELE(vp);
                    474:        splx(si);
                    475: }
                    476: 
                    477: /*
                    478:  * Purge blocks for filesystem mp from incore cache
                    479:  * before umount().
                    480:  */
                    481: mpurgemp(mp)
                    482:        struct mount *mp;
                    483: {
                    484:        register struct cmap *c1, *c2;
                    485:        register int i;
                    486:        int s = splimp();
                    487: 
                    488: more:
                    489:        for (i = 0; i < CMHSIZ; i++) {
                    490:                c1 = &cmap[cmhash[i]];
                    491:                if (c1 == ecmap)
                    492:                        continue;
                    493:                if (mp == NULL || c1->c_vp->v_mount == mp)
                    494:                        cmhash[i] = c1->c_hlink;
                    495:                else {
                    496:                        for (;;) {
                    497:                                c2 = c1;
                    498:                                c1 = &cmap[c1->c_hlink];
                    499:                                if (c1 == ecmap)
                    500:                                        goto cont;
                    501:                                if (c1->c_vp->v_mount == mp)
                    502:                                        break;
                    503:                        }
                    504:                        c2->c_hlink = c1->c_hlink;
                    505:                }
                    506:                (void) splx(s);
                    507:                HOLDRELE(c1->c_vp);
                    508:                s = splimp();
                    509:                c1->c_vp = NULLVP;
                    510:                c1->c_blkno = 0;
                    511:                c1->c_hlink = 0;
                    512:                goto more;
                    513: cont:
                    514:                ;
                    515:        }
                    516:        (void) splx(s);
                    517: }
                    518: 
                    519: /*
                    520:  * Initialize core map
                    521:  */
                    522: meminit(first, last)
                    523:        int first, last;
                    524: {
                    525:        register int i;
                    526:        register struct cmap *c;
                    527: 
                    528:        firstfree = clrnd(first);
                    529:        maxfree = clrnd(last - (CLSIZE - 1));
                    530:        freemem = maxfree - firstfree;
                    531:        ecmx = ecmap - cmap;
                    532:        if (ecmx < freemem / CLSIZE)
                    533:                freemem = ecmx * CLSIZE;
                    534:        for (i = 1; i <= freemem / CLSIZE; i++) {
                    535:                cmap[i-1].c_next = i;
                    536:                c = &cmap[i];
                    537:                c->c_prev = i-1;
                    538:                c->c_free = 1;
                    539:                c->c_gone = 1;
                    540:                c->c_type = CSYS;
                    541:                c->c_blkno = 0;
                    542:        }
                    543:        cmap[freemem / CLSIZE].c_next = CMHEAD;
                    544:        for (i = 0; i < CMHSIZ; i++)
                    545:                cmhash[i] = ecmx;
                    546:        cmap[CMHEAD].c_prev = freemem / CLSIZE;
                    547:        cmap[CMHEAD].c_type = CSYS;
                    548:        avefree = freemem;
                    549: }
                    550: 
                    551: #ifdef notdef
                    552: /*
                    553:  * Wait for frame pf to become unlocked
                    554:  * if it is currently locked.
                    555:  */
                    556: mwait(c)
                    557:        struct cmap *c;
                    558: {
                    559: 
                    560:        mlock(c);
                    561:        munlock(c);
                    562: }
                    563: 
                    564: /*
                    565:  * Lock a page frame.
                    566:  */
                    567: mlock(c)
                    568:        register struct cmap *c;
                    569: {
                    570: 
                    571:        while (c->c_lock) {
                    572:                c->c_want = 1;
                    573:                sleep((caddr_t)c, PSWP+1);
                    574:        }
                    575:        c->c_lock = 1;
                    576: }
                    577: 
                    578: /*
                    579:  * Unlock a page frame.
                    580:  */
                    581: munlock(c)
                    582:        register struct cmap *c;
                    583: {
                    584: 
                    585:        if (c->c_lock == 0)
                    586:                panic("dup page unlock");
                    587:        if (c->c_want) {
                    588:                wakeup((caddr_t)c);
                    589:                c->c_want = 0;
                    590:        }
                    591:        c->c_lock = 0;
                    592: }
                    593: #endif
                    594: 
                    595: /* 
                    596:  * Lock a virtual segment.
                    597:  *
                    598:  * For each cluster of pages, if the cluster is not valid,
                    599:  * touch it to fault it in, otherwise just lock page frame.
                    600:  * Called from physio to ensure that the pages 
                    601:  * participating in raw i/o are valid and locked.
                    602:  */
                    603: vslock(base, count)
                    604:        caddr_t base;
                    605: {
                    606:        register unsigned v;
                    607:        register int npf;
                    608:        register struct pte *pte;
                    609:        register struct cmap *c;
                    610: 
                    611: #if defined(tahoe)
                    612:        /*
                    613:         * TAHOE I/O drivers may arrive here on raw I/O,
                    614:         * base will be a system address in this case
                    615:         */
                    616:        if (((int)base & KERNBASE) == KERNBASE)         /* system addresses */
                    617:                return;
                    618: #endif
                    619:        v = clbase(btop(base));
                    620:        pte = vtopte(u.u_procp, v);
                    621:        npf = btoc(count + ((int)base & CLOFSET));
                    622:        for (; npf > 0; pte += CLSIZE, v += CLSIZE, npf -= CLSIZE) {
                    623: retry:
                    624:                if (pte->pg_v) {
                    625: #ifdef MAPMEM
                    626:                        if (pte->pg_fod)        /* mapped page */
                    627:                                continue;
                    628: #endif
                    629:                        c = &cmap[pgtocm(pte->pg_pfnum)];
                    630:                        if (c->c_lock) {
                    631:                                MLOCK(c);
                    632:                                MUNLOCK(c);
                    633:                                goto retry;
                    634:                        }
                    635:                        MLOCK(c);
                    636:                } else
                    637:                        pagein(ctob(v), 1);     /* return it locked */
                    638:        }
                    639: }
                    640: 
                    641: /* 
                    642:  * Unlock a virtual segment.
                    643:  */
                    644: vsunlock(base, count, rw)
                    645:        caddr_t base;
                    646: {
                    647:        register struct pte *pte;
                    648:        register struct cmap *c;
                    649:        unsigned v;
                    650:        int npf;
                    651: 
                    652: #if defined(tahoe)
                    653:        /*
                    654:         * TAHOE I/O drivers may arrive here on raw I/O,
                    655:         * base will be a system address in this case
                    656:         */
                    657:        if (((int)base & KERNBASE) == KERNBASE)         /* system addresses */
                    658:                return;
                    659: #endif
                    660:        v = clbase(btop(base));
                    661:        pte = vtopte(u.u_procp, v);
                    662:        npf = btoc(count + ((int)base & CLOFSET));
                    663:        for (; npf > 0; pte += CLSIZE, npf -= CLSIZE) {
                    664: #ifdef MAPMEM
                    665:                if (pte->pg_fod && pte->pg_v)   /* mapped page */
                    666:                        continue;
                    667: #endif
                    668:                c = &cmap[pgtocm(pte->pg_pfnum)];
                    669:                MUNLOCK(c);
                    670:                if (rw == B_READ)       /* Reading from device writes memory */
                    671:                        pte->pg_m = 1;
                    672:        }
                    673: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.