Annotation of researchv9/sys.vax/sys/vmmem.c, revision 1.1.1.1

1.1       root        1: /*     vmmem.c 4.7     81/07/09        */
                      2: 
                      3: #include "../h/param.h"
                      4: #include "../h/systm.h"
                      5: #include "../h/pte.h"
                      6: #include "../h/cmap.h"
                      7: #include "../h/dir.h"
                      8: #include "../h/user.h"
                      9: #include "../h/proc.h"
                     10: #include "../h/mtpr.h"
                     11: #include "../h/text.h"
                     12: #include "../h/vm.h"
                     13: #include "../h/file.h"
                     14: #include "../h/inode.h"
                     15: #include "../h/buf.h"
                     16: #include "../h/mount.h"
                     17: #include "../h/trace.h"
                     18: #include "../h/map.h"
                     19: 
                     20: /*
                     21:  * Allocate memory, and always succeed
                     22:  * by jolting page-out daemon
                     23:  * so as to obtain page frames.
                     24:  * To be used in conjunction with vmemfree().
                     25:  */
                     26: vmemall(pte, size, p, type)
                     27:        register struct pte *pte;
                     28:        int size;
                     29:        struct proc *p;
                     30: {
                     31:        register int m;
                     32: 
                     33:        if (size <= 0 || size > maxmem)
                     34:                panic("vmemall size");
                     35:        while (size > 0) {
                     36:                if (freemem < desfree)
                     37:                        wakeup((caddr_t)&proc[2]);      /* jolt daemon */
                     38:                while (freemem == 0)
                     39:                        sleep((caddr_t)&freemem, PSWP+2);
                     40:                m = imin(size, freemem);
                     41:                (void) memall(pte, m, p, type);
                     42:                size -= m;
                     43:                pte += m;
                     44:        }
                     45:        if (freemem < desfree)
                     46:                wakeup((caddr_t)&proc[2]);              /* jolt daemon */
                     47:        /*
                     48:         * Always succeeds, but return success for
                     49:         * vgetu and vgetpt (e.g.) which call either
                     50:         * memall or vmemall depending on context.
                     51:         */
                     52:        return (1);
                     53: }
                     54: 
                     55: /*
                     56:  * Free valid and reclaimable page frames belonging to the
                     57:  * count pages starting at pte.  If a page is valid
                     58:  * or reclaimable and locked (but not a system page), then
                     59:  * we simply mark the page as c_gone and let the pageout
                     60:  * daemon free the page when it is through with it.
                     61:  * If a page is reclaimable, and already in the free list, then
                     62:  * we mark the page as c_gone, and (of course) don't free it.
                     63:  *
                     64:  * Determines the largest contiguous cluster of
                     65:  * valid pages and frees them in one call to memfree.
                     66:  */
                     67: vmemfree(pte, count)
                     68:        register struct pte *pte;
                     69:        register int count;
                     70: {
                     71:        register struct cmap *c;
                     72:        register struct pte *spte;
                     73:        register int j;
                     74:        int size, pcnt, fileno;
                     75: 
                     76:        if (count % CLSIZE)
                     77:                panic("vmemfree");
                     78:        for (size = 0, pcnt = 0; count > 0; pte += CLSIZE, count -= CLSIZE) {
                     79:                if (pte->pg_fod == 0 && pte->pg_pfnum) {
                     80:                        c = &cmap[pgtocm(pte->pg_pfnum)];
                     81:                        pcnt += CLSIZE;
                     82:                        if (c->c_lock && c->c_type != CSYS) {
                     83:                                for (j = 0; j < CLSIZE; j++)
                     84:                                        *(int *)(pte+j) &= (PG_PROT|PG_VREADM);
                     85:                                c->c_gone = 1;
                     86:                                goto free;
                     87:                        }
                     88:                        if (c->c_free) {
                     89:                                pcnt -= CLSIZE;
                     90:                                for (j = 0; j < CLSIZE; j++)
                     91:                                        *(int *)(pte+j) &= (PG_PROT|PG_VREADM);
                     92:                                if (c->c_type == CTEXT)
                     93:                                        distpte(&text[c->c_ndx], (int)c->c_page, pte);
                     94:                                c->c_gone = 1;
                     95:                                goto free;
                     96:                        }
                     97:                        if (size == 0)
                     98:                                spte = pte;
                     99:                        size += CLSIZE;
                    100:                        continue;
                    101:                }
                    102:                if (pte->pg_fod) {
                    103:                        fileno = ((struct fpte *)pte)->pg_source + PG_FMIN;
                    104:                        if (fileno > PG_FMAX)
                    105:                                panic("vmemfree pg_source");
                    106:                        if (fileno < NOFILE)
                    107:                                panic("vmemfree, vrpages ref'd");
                    108:                        for (j = 0; j < CLSIZE; j++)
                    109:                                *(int *)(pte+j) &= (PG_PROT|PG_VREADM);
                    110:                }
                    111: free:
                    112:                if (size) {
                    113:                        memfree(spte, size, 1);
                    114:                        size = 0;
                    115:                }
                    116:        }
                    117:        if (size)
                    118:                memfree(spte, size, 1);
                    119:        return (pcnt);
                    120: }
                    121: 
                    122: /*
                    123:  * Unlink a page frame from the free list -
                    124:  *
                    125:  * Performed if the page being reclaimed
                    126:  * is in the free list.
                    127:  */
                    128: munlink(pf)
                    129:        unsigned pf;
                    130: {
                    131:        register int next, prev;
                    132: 
                    133:        next = cmap[pgtocm(pf)].c_next;
                    134:        prev = cmap[pgtocm(pf)].c_prev;
                    135:        cmap[prev].c_next = next;
                    136:        cmap[next].c_prev = prev;
                    137:        cmap[pgtocm(pf)].c_free = 0;
                    138:        if (freemem < minfree)
                    139:                wakeup((caddr_t)&proc[2]);      /* jolt paging daemon */
                    140:        freemem -= CLSIZE;
                    141: }
                    142: 
                    143: /*
                    144:  * Allocate memory -
                    145:  *
                    146:  * The free list appears as a doubly linked list
                    147:  * in the core map with cmap[0] serving as a header.
                    148:  */
                    149: memall(pte, size, p, type)
                    150:        register struct pte *pte;
                    151:        int size;
                    152:        struct proc *p;
                    153: {
                    154:        register struct cmap *c;
                    155:        register struct pte *rpte;
                    156:        register struct proc *rp;
                    157:        int i, j, next, curpos;
                    158:        unsigned pf;
                    159:        struct cmap *c1, *c2;
                    160: 
                    161:        if (size % CLSIZE)
                    162:                panic("memall");
                    163:        if (size > freemem)
                    164:                return (0);
                    165:        trace(TR_MALL, size, u.u_procp->p_pid);
                    166:        for (i = size; i > 0; i -= CLSIZE) {
                    167:                curpos = cmap[CMHEAD].c_next;
                    168:                c = &cmap[curpos];
                    169:                if (c->c_free == 0)
                    170:                        panic("dup mem alloc");
                    171:                if (cmtopg(curpos) > maxfree)
                    172:                        panic("bad mem alloc");
                    173:                if (c->c_gone == 0 && c->c_type != CSYS) {
                    174:                        if (c->c_type == CTEXT)
                    175:                                rp = text[c->c_ndx].x_caddr;
                    176:                        else
                    177:                                rp = &proc[c->c_ndx];
                    178:                        while (rp->p_flag & SNOVM)
                    179:                                rp = rp->p_xlink;
                    180:                        switch (c->c_type) {
                    181: 
                    182:                        case CTEXT:
                    183:                                rpte = tptopte(rp, c->c_page);
                    184:                                break;
                    185: 
                    186:                        case CDATA:
                    187:                                rpte = dptopte(rp, c->c_page);
                    188:                                break;
                    189: 
                    190:                        case CSTACK:
                    191:                                rpte = sptopte(rp, c->c_page);
                    192:                                break;
                    193:                        }
                    194:                        zapcl(rpte, pg_pfnum) = 0;
                    195:                        if (c->c_type == CTEXT)
                    196:                                distpte(&text[c->c_ndx], (int)c->c_page, rpte);
                    197:                }
                    198:                switch (type) {
                    199: 
                    200:                case CSYS:
                    201:                        c->c_ndx = p->p_ndx;
                    202:                        break;
                    203: 
                    204:                case CTEXT:
                    205:                        c->c_page = vtotp(p, ptetov(p, pte));
                    206:                        c->c_ndx = p->p_textp - &text[0];
                    207:                        break;
                    208: 
                    209:                case CDATA:
                    210:                        c->c_page = vtodp(p, ptetov(p, pte));
                    211:                        c->c_ndx = p->p_ndx;
                    212:                        break;
                    213: 
                    214:                case CSTACK:
                    215:                        c->c_page = vtosp(p, ptetov(p, pte));
                    216:                        c->c_ndx = p->p_ndx;
                    217:                        break;
                    218:                }
                    219:                if (c->c_blkno) {
                    220:                        /*
                    221:                         * This is very like munhash(), except
                    222:                         * that we really don't want to bother
                    223:                         * to calculate a dev to pass to it.
                    224:                         */
                    225:                        j = CMHASH(c->c_blkno);
                    226:                        c1 = &cmap[cmhash[j]];
                    227:                        if (c1 == c)
                    228:                                cmhash[j] = c1->c_hlink;
                    229:                        else {
                    230:                                for (;;) {
                    231:                                        if (c1 == ecmap)
                    232:                                                panic("memall ecmap");
                    233:                                        c2 = c1;
                    234:                                        c1 = &cmap[c2->c_hlink];
                    235:                                        if (c1 == c)
                    236:                                                break;
                    237:                                }
                    238:                                c2->c_hlink = c1->c_hlink;
                    239:                        }
                    240:                        if (mfind(c->c_mdev == MSWAPX ?
                    241:                              swapdev : mount[c->c_mdev].m_dev,
                    242:                              (daddr_t)c->c_blkno))
                    243:                                panic("memall mfind");
                    244:                        c1->c_mdev = 0;
                    245:                        c1->c_blkno = 0;
                    246:                        c1->c_hlink = 0;
                    247:                }
                    248:                pf = cmtopg(curpos);
                    249:                for (j = 0; j < CLSIZE; j++)
                    250:                        *(int *)pte++ = pf++;
                    251:                c->c_free = 0;
                    252:                c->c_gone = 0;
                    253:                if (c->c_intrans || c->c_want)
                    254:                        panic("memall intrans|want");
                    255:                c->c_lock = 1;
                    256:                c->c_type = type;
                    257:                freemem -= CLSIZE;
                    258:                next = c->c_next;
                    259:                cmap[CMHEAD].c_next = next;
                    260:                cmap[next].c_prev = CMHEAD;
                    261:        }
                    262:        return (size);
                    263: }
                    264: 
                    265: /*
                    266:  * Free memory -
                    267:  *
                    268:  * The page frames being returned are inserted
                    269:  * to the head/tail of the free list depending
                    270:  * on whether there is any possible future use of them.
                    271:  *
                    272:  * If the freemem count had been zero,
                    273:  * the processes sleeping for memory
                    274:  * are awakened.
                    275:  */
                    276: memfree(pte, size, detach)
                    277:        register struct pte *pte;
                    278:        register int size;
                    279: {
                    280:        register int i, j, prev, next;
                    281:        register struct cmap *c;
                    282:        
                    283:        if (size % CLSIZE)
                    284:                panic("memfree");
                    285:        if (freemem < CLSIZE * KLMAX)
                    286:                wakeup((caddr_t)&freemem);
                    287:        while (size > 0) {
                    288:                size -= CLSIZE;
                    289:                i = pte->pg_pfnum;
                    290:                if (i < firstfree || i > maxfree)
                    291:                        panic("bad mem free");
                    292:                i = pgtocm(i);
                    293:                c = &cmap[i];
                    294:                if (c->c_free)
                    295:                        panic("dup mem free");
                    296:                if (detach && c->c_type != CSYS) {
                    297:                        for (j = 0; j < CLSIZE; j++)
                    298:                                *(int *)(pte+j) &= (PG_PROT|PG_VREADM);
                    299:                        c->c_gone = 1;
                    300:                }
                    301:                if (detach && c->c_blkno == 0) {
                    302:                        next = cmap[CMHEAD].c_next;
                    303:                        cmap[next].c_prev = i;
                    304:                        c->c_prev = CMHEAD;
                    305:                        c->c_next = next;
                    306:                        cmap[CMHEAD].c_next = i;
                    307:                } else {
                    308:                        prev = cmap[CMHEAD].c_prev;
                    309:                        cmap[prev].c_next = i;
                    310:                        c->c_next = CMHEAD;
                    311:                        c->c_prev = prev;
                    312:                        cmap[CMHEAD].c_prev = i;
                    313:                }
                    314:                c->c_free = 1;
                    315:                freemem += CLSIZE;
                    316:                pte += CLSIZE;
                    317:        }
                    318: }
                    319: 
                    320: /*
                    321:  * Allocate wired-down (non-paged) pages in kernel virtual memory.
                    322:  */
                    323: caddr_t
                    324: wmemall(pmemall, n)
                    325:        int (*pmemall)(), n;
                    326: {
                    327:        int npg;
                    328:        caddr_t va;
                    329:        register int a;
                    330: 
                    331:        npg = btoc(n);
                    332:        a = rmalloc(kernelmap, npg);
                    333:        if (a == 0)
                    334:                return (0);
                    335:        if ((*pmemall)(&Usrptmap[a], npg, &proc[0], CSYS) == 0) {
                    336:                rmfree(kernelmap, npg, a);
                    337:                return (0);
                    338:        }
                    339:        va = (caddr_t) kmxtob(a);
                    340:        vmaccess(&Usrptmap[a], va, npg);
                    341:        return (va);
                    342: }
                    343: 
                    344: wmemfree(va, n)
                    345:        caddr_t va;
                    346:        int n;
                    347: {
                    348:        register int a;
                    349:        int npg;
                    350: 
                    351:        a = btokmx((struct pte *) va);
                    352:        npg = btoc(n);
                    353:        (void) memfree(&Usrptmap[a], npg, 0);
                    354:        rmfree(kernelmap, npg, a);
                    355: }
                    356: 
                    357: /*
                    358:  * Enter clist block c on the hash chains.
                    359:  * It contains file system block bn from device dev.
                    360:  * Dev must either be a mounted file system or the swap device
                    361:  * so we panic if getfsx() cannot find it.
                    362:  */
                    363: mhash(c, dev, bn)
                    364:        register struct cmap *c;
                    365:        dev_t dev;
                    366:        daddr_t bn;
                    367: {
                    368:        register int i = CMHASH(bn);
                    369: 
                    370:        c->c_hlink = cmhash[i];
                    371:        cmhash[i] = c - cmap;
                    372:        c->c_blkno = bn;
                    373:        i = getfsx(dev);
                    374:        if (i == -1)
                    375:                panic("mhash");
                    376:        c->c_mdev = i;
                    377: }
                    378: 
                    379: /*
                    380:  * Pull the clist entry of <dev,bn> off the hash chains.
                    381:  * We have checked before calling (using mfind) that the
                    382:  * entry really needs to be unhashed, so panic if we can't
                    383:  * find it (can't happen).
                    384:  */
                    385: munhash(dev, bn)
                    386:        dev_t dev;
                    387:        daddr_t bn;
                    388: {
                    389:        register int i = CMHASH(bn);
                    390:        register struct cmap *c1, *c2;
                    391: 
                    392:        c1 = &cmap[cmhash[i]];
                    393:        if (c1 == ecmap)
                    394:                panic("munhash");
                    395:        if (c1->c_blkno == bn && getfsx(dev) == c1->c_mdev)
                    396:                cmhash[i] = c1->c_hlink;
                    397:        else {
                    398:                for (;;) {
                    399:                        c2 = c1;
                    400:                        c1 = &cmap[c2->c_hlink];
                    401:                        if (c1 == ecmap)
                    402:                                panic("munhash");
                    403:                        if (c1->c_blkno == bn && getfsx(dev) == c1->c_mdev)
                    404:                                break;
                    405:                }
                    406:                c2->c_hlink = c1->c_hlink;
                    407:        }
                    408:        if (mfind(dev, bn))
                    409:                panic("munhash mfind");
                    410:        c1->c_mdev = 0;
                    411:        c1->c_blkno = 0;
                    412:        c1->c_hlink = 0;
                    413: }
                    414: 
                    415: /*
                    416:  * Look for block bn of device dev in the free pool.
                    417:  * Currently it should not be possible to find it unless it is
                    418:  * c_free and c_gone, although this may later not be true.
                    419:  * (This is because active texts are locked against file system
                    420:  * writes by the system.)
                    421:  */
                    422: struct cmap *
                    423: mfind(dev, bn)
                    424:        dev_t dev;
                    425:        daddr_t bn;
                    426: {
                    427:        register struct cmap *c1 = &cmap[cmhash[CMHASH(bn)]];
                    428: 
                    429:        while (c1 != ecmap) {
                    430:                if (c1->c_blkno == bn && c1->c_mdev == getfsx(dev))
                    431:                        return (c1);
                    432:                c1 = &cmap[c1->c_hlink];
                    433:        }
                    434:        return ((struct cmap *)0);
                    435: }
                    436: 
                    437: /*
                    438:  * Purge blocks from device dev from incore cache
                    439:  * before umount().
                    440:  */
                    441: mpurge(mdev)
                    442:        int mdev;
                    443: {
                    444:        register struct cmap *c1, *c2;
                    445:        register int i;
                    446: 
                    447:        for (i = 0; i < CMHSIZ; i++) {
                    448: more:
                    449:                c1 = &cmap[cmhash[i]];
                    450:                if (c1 == ecmap)
                    451:                        continue;
                    452:                if (c1->c_mdev == mdev)
                    453:                        cmhash[i] = c1->c_hlink;
                    454:                else {
                    455:                        for (;;) {
                    456:                                c2 = c1;
                    457:                                c1 = &cmap[c1->c_hlink];
                    458:                                if (c1 == ecmap)
                    459:                                        goto cont;
                    460:                                if (c1->c_mdev == mdev)
                    461:                                        break;
                    462:                        }
                    463:                        c2->c_hlink = c1->c_hlink;
                    464:                }
                    465:                c1->c_mdev = 0;
                    466:                c1->c_blkno = 0;
                    467:                c1->c_hlink = 0;
                    468:                goto more;
                    469: cont:
                    470:                ;
                    471:        }
                    472: }
                    473: 
                    474: /*
                    475:  * Initialize core map
                    476:  */
                    477: meminit(first, last)
                    478:        int first, last;
                    479: {
                    480:        register int i;
                    481:        register struct cmap *c;
                    482: 
                    483:        firstfree = clrnd(first);
                    484:        maxfree = clrnd(last - (CLSIZE - 1));
                    485:        freemem = maxfree - firstfree;
                    486:        ecmx = ecmap - cmap;
                    487:        if (ecmx < freemem / CLSIZE)
                    488:                freemem = ecmx * CLSIZE;
                    489:        for (i = 1; i <= freemem / CLSIZE; i++) {
                    490:                cmap[i-1].c_next = i;
                    491:                c = &cmap[i];
                    492:                c->c_prev = i-1;
                    493:                c->c_free = 1;
                    494:                c->c_gone = 1;
                    495:                c->c_type = CSYS;
                    496:                c->c_mdev = 0;
                    497:                c->c_blkno = 0;
                    498:        }
                    499:        cmap[freemem / CLSIZE].c_next = CMHEAD;
                    500:        for (i = 0; i < CMHSIZ; i++)
                    501:                cmhash[i] = ecmx;
                    502:        cmap[CMHEAD].c_prev = freemem / CLSIZE;
                    503:        cmap[CMHEAD].c_type = CSYS;
                    504:        avefree = freemem;
                    505:        hand = 0;
                    506: }
                    507: 
                    508: /*
                    509:  * Wait for frame pf to become unlocked
                    510:  * if it is currently locked.
                    511:  *
                    512:  * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
                    513:  */
                    514: mwait(pf)
                    515:        unsigned pf;
                    516: {
                    517: 
                    518:        mlock(pf);
                    519:        munlock(pf);
                    520: }
                    521: 
                    522: /*
                    523:  * Lock a page frame.
                    524:  *
                    525:  * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
                    526:  */
                    527: mlock(pf)
                    528:        unsigned pf;
                    529: {
                    530:        register struct cmap *c = &cmap[pgtocm(pf)];
                    531: 
                    532:        while (c->c_lock) {
                    533:                c->c_want = 1;
                    534:                sleep((caddr_t)c, PSWP+1);
                    535:        }
                    536:        c->c_lock = 1;
                    537: }
                    538: 
                    539: /*
                    540:  * Unlock a page frame.
                    541:  *
                    542:  * THIS ROUTINE SHOULD TAKE A CMAP STRUCTURE AS ARGUMENT.
                    543:  */
                    544: munlock(pf)
                    545:        unsigned pf;
                    546: {
                    547:        register struct cmap *c = &cmap[pgtocm(pf)];
                    548: 
                    549:        if (c->c_lock == 0)
                    550:                panic("dup page unlock");
                    551:        if (c->c_want)
                    552:                wakeup((caddr_t)c);
                    553:        c->c_lock = 0;
                    554:        c->c_want = 0;
                    555: }
                    556: 
                    557: /* 
                    558:  * Lock a virtual segment.
                    559:  *
                    560:  * For each cluster of pages, if the cluster is not valid,
                    561:  * touch it to fault it in, otherwise just lock page frame.
                    562:  * Called from physio to ensure that the pages 
                    563:  * participating in raw i/o are valid and locked.
                    564:  * We use SDLYU to keep pagein from unlocking pages,
                    565:  * so they make it safely back here locked.
                    566:  */
                    567: vslock(base, count)
                    568:        caddr_t base;
                    569: {
                    570:        register unsigned v;
                    571:        register int npf;
                    572:        register struct pte *pte;
                    573: 
                    574:        u.u_procp->p_flag |= SDLYU;
                    575:        v = btop(base);
                    576:        pte = vtopte(u.u_procp, v);
                    577:        npf = btoc(count + ((int)base & CLOFSET));
                    578:        while (npf > 0) {
                    579:                if (pte->pg_v) 
                    580:                        mlock(pte->pg_pfnum);
                    581:                else
                    582:                        if (fubyte((caddr_t)ctob(v)) < 0)
                    583:                                panic("vslock");
                    584:                pte += CLSIZE;
                    585:                v += CLSIZE;
                    586:                npf -= CLSIZE;
                    587:        }
                    588:        u.u_procp->p_flag &= ~SDLYU;
                    589: }
                    590: 
                    591: /* 
                    592:  * Unlock a virtual segment.
                    593:  */
                    594: vsunlock(base, count, rw)
                    595:        caddr_t base;
                    596: {
                    597:        register struct pte *pte;
                    598:        register int npf;
                    599: 
                    600:        pte = vtopte(u.u_procp, btop(base));
                    601:        npf = btoc(count + ((int)base & CLOFSET));
                    602:        while (npf > 0) {
                    603:                munlock(pte->pg_pfnum);
                    604:                if (rw == B_READ)       /* Reading from device writes memory */
                    605:                        pte->pg_m = 1;
                    606:                pte += CLSIZE;
                    607:                npf -= CLSIZE;
                    608:        }
                    609: }

unix.superglobalmegacorp.com

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