Annotation of researchv10no/sys/vm/vmmem.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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