Annotation of lucent/sys/src/9/port/swap.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "../port/error.h"
        !             7: 
        !             8: int    canflush(Proc *p, Segment*);
        !             9: void   executeio(void);
        !            10: int    needpages(void*);
        !            11: void   pageout(Proc *p, Segment*);
        !            12: void   pagepte(int, Page**);
        !            13: void   pager(void*);
        !            14: 
        !            15:        Image   swapimage;
        !            16: static         int     swopen;
        !            17: static Page    **iolist;
        !            18: static int     ioptr;
        !            19: static int     maxpages;
        !            20: 
        !            21: void
        !            22: swapinit(void)
        !            23: {
        !            24:        swapalloc.swmap = xalloc(conf.nswap);
        !            25:        swapalloc.top = &swapalloc.swmap[conf.nswap];
        !            26:        swapalloc.alloc = swapalloc.swmap;
        !            27:        swapalloc.last = swapalloc.swmap;
        !            28:        swapalloc.free = conf.nswap;
        !            29:        maxpages = SEGMAXSIZE/BY2PG;
        !            30:        if(maxpages > conf.nswap/2)
        !            31:                maxpages = conf.nswap/2;
        !            32:        iolist = xalloc(maxpages*sizeof(Page*));
        !            33:        if(swapalloc.swmap == 0 || iolist == 0)
        !            34:                panic("swapinit: not enough memory");
        !            35: }
        !            36: 
        !            37: ulong
        !            38: newswap(void)
        !            39: {
        !            40:        uchar *look;
        !            41: 
        !            42:        lock(&swapalloc);
        !            43:        if(swapalloc.free == 0)
        !            44:                panic("out of swap space");
        !            45: 
        !            46:        look = memchr(swapalloc.last, 0, swapalloc.top-swapalloc.last);
        !            47:        if(look == 0)
        !            48:                panic("inconsistent swap");
        !            49:        
        !            50:        *look = 1;
        !            51:        swapalloc.last = look;
        !            52:        swapalloc.free--;
        !            53:        unlock(&swapalloc);
        !            54:        return (look-swapalloc.swmap) * BY2PG; 
        !            55: }
        !            56: 
        !            57: void
        !            58: putswap(Page *p)
        !            59: {
        !            60:        uchar *idx;
        !            61: 
        !            62:        lock(&swapalloc);
        !            63:        idx = &swapalloc.swmap[((ulong)p)/BY2PG];
        !            64:        if(--(*idx) == 0) {
        !            65:                swapalloc.free++;
        !            66:                if(idx < swapalloc.last)
        !            67:                        swapalloc.last = idx;
        !            68:        }
        !            69:        unlock(&swapalloc);
        !            70: }
        !            71: 
        !            72: void
        !            73: dupswap(Page *p)
        !            74: {
        !            75:        lock(&swapalloc);
        !            76:        swapalloc.swmap[((ulong)p)/BY2PG]++;
        !            77:        unlock(&swapalloc);
        !            78: }
        !            79: 
        !            80: void
        !            81: kickpager(void)
        !            82: {
        !            83:        static int started;
        !            84: 
        !            85:        if(started)
        !            86:                wakeup(&swapalloc.r);
        !            87:        else {
        !            88:                kproc("pager", pager, 0);
        !            89:                started = 1;
        !            90:        }
        !            91: }
        !            92: 
        !            93: void
        !            94: pager(void *junk)
        !            95: {
        !            96:        int i;
        !            97:        Proc *p, *ep;
        !            98:        Segment *s, *ts;
        !            99: 
        !           100:        if(waserror()) 
        !           101:                panic("pager: os error\n");
        !           102: 
        !           103:        USED(junk);
        !           104:        p = proctab(0);
        !           105:        ep = &p[conf.nproc];
        !           106: 
        !           107: loop:
        !           108:        u->p->psstate = "Idle";
        !           109:        sleep(&swapalloc.r, needpages, 0);
        !           110: 
        !           111:        while(needpages(junk)) {
        !           112:                p++;
        !           113:                if(p >= ep)
        !           114:                        p = proctab(0);
        !           115: 
        !           116:                if(p->state == Dead || p->kp)
        !           117:                        continue;
        !           118: 
        !           119:                /* don't swap out programs from devroot.c - they
        !           120:                 * supply important system services
        !           121:                 */
        !           122:                ts = p->seg[TSEG];
        !           123:                if(ts && ts->image && devchar[ts->image->c->type] == '/')
        !           124:                        continue;
        !           125: 
        !           126:                if(swapimage.c) {
        !           127:                        for(i = 0; i < NSEG; i++) {
        !           128:                                if(!needpages(junk))
        !           129:                                        goto loop;
        !           130: 
        !           131:                                if(s = p->seg[i]) {
        !           132:                                        switch(s->type&SG_TYPE) {
        !           133:                                        default:
        !           134:                                                break;
        !           135:                                        case SG_TEXT:
        !           136:                                                pageout(p, s);
        !           137:                                                break;
        !           138:                                        case SG_DATA:
        !           139:                                        case SG_BSS:
        !           140:                                        case SG_STACK:
        !           141:                                        case SG_SHARED:
        !           142:                                                u->p->psstate = "Pageout";
        !           143:                                                pageout(p, s);
        !           144:                                                if(ioptr != 0) {
        !           145:                                                        u->p->psstate = "I/O";
        !           146:                                                        executeio();
        !           147:                                                }
        !           148:                                        }
        !           149:                                }
        !           150:                        }
        !           151:                        continue;
        !           152:                }
        !           153: 
        !           154:                if(palloc.freecount < swapalloc.highwater) {
        !           155:                        if(!cpuserver)
        !           156:                                freebroken();   /* can use the memory */
        !           157: 
        !           158:                        /* Emulate the old system if no swap channel */
        !           159:                        print("no physical memory\n");
        !           160:                        tsleep(&swapalloc.r, return0, 0, 1000);
        !           161:                        wakeup(&palloc.r);
        !           162:                }
        !           163:        }
        !           164:        goto loop;
        !           165: }
        !           166: 
        !           167: void                   
        !           168: pageout(Proc *p, Segment *s)
        !           169: {
        !           170:        int type, i;
        !           171:        Pte *l;
        !           172:        Page **pg, *entry;
        !           173: 
        !           174:        if(!canqlock(&s->lk))   /* We cannot afford to wait, we will surely deadlock */
        !           175:                return;
        !           176: 
        !           177:        if(s->steal) {          /* Protected by /dev/proc */
        !           178:                qunlock(&s->lk);
        !           179:                return;
        !           180:        }
        !           181: 
        !           182:        if(!canflush(p, s)) {   /* Able to invalidate all tlbs with references */
        !           183:                qunlock(&s->lk);
        !           184:                putseg(s);
        !           185:                return;
        !           186:        }
        !           187: 
        !           188:        if(waserror()) {
        !           189:                qunlock(&s->lk);
        !           190:                putseg(s);
        !           191:                return;
        !           192:        }
        !           193: 
        !           194:        /* Pass through the pte tables looking for memory pages to swap out */
        !           195:        type = s->type&SG_TYPE;
        !           196:        for(i = 0; i < SEGMAPSIZE; i++) {
        !           197:                l = s->map[i];
        !           198:                if(l == 0)
        !           199:                        continue;
        !           200:                for(pg = l->first; pg < l->last; pg++) {
        !           201:                        entry = *pg;
        !           202:                        if(pagedout(entry))
        !           203:                                continue;
        !           204: 
        !           205:                        if(entry->modref & PG_REF) {
        !           206:                                entry->modref &= ~PG_REF;
        !           207:                                continue;
        !           208:                        }
        !           209: 
        !           210:                        while(swapalloc.free == 0) {
        !           211:                                if(ioptr != 0)
        !           212:                                        goto out;
        !           213: 
        !           214:                                print("out of swap space\n");
        !           215:                                tsleep(&swapalloc.r, return0, 0, 1000);
        !           216:                        }
        !           217: 
        !           218:                        pagepte(type, pg);
        !           219: 
        !           220:                        if(ioptr >= maxpages)
        !           221:                                goto out;
        !           222:                }
        !           223:        }
        !           224: out:
        !           225:        poperror();
        !           226:        qunlock(&s->lk);
        !           227:        putseg(s);
        !           228:        wakeup(&palloc.r);
        !           229: }
        !           230: 
        !           231: int
        !           232: canflush(Proc *p, Segment *s)
        !           233: {
        !           234:        int i;
        !           235:        Proc *ep;
        !           236: 
        !           237:        lock(s);
        !           238:        if(s->ref == 1) {               /* Easy if we are the only user */
        !           239:                s->ref++;
        !           240:                unlock(s);
        !           241:                return canpage(p);
        !           242:        }
        !           243:        s->ref++;
        !           244:        unlock(s);
        !           245: 
        !           246:        /* Now we must do hardwork to ensure all processes which have tlb
        !           247:         * entries for this segment will be flushed if we suceed in pageing it out
        !           248:         */
        !           249:        p = proctab(0);
        !           250:        ep = &p[conf.nproc];
        !           251:        while(p < ep) {
        !           252:                if(p->state != Dead) {
        !           253:                        for(i = 0; i < NSEG; i++)
        !           254:                                if(p->seg[i] == s)
        !           255:                                        if(!canpage(p))
        !           256:                                                return 0;
        !           257:                }
        !           258:                p++;
        !           259:        }
        !           260:        return 1;                                               
        !           261: }
        !           262: 
        !           263: void
        !           264: pagepte(int type, Page **pg)
        !           265: {
        !           266:        ulong daddr;
        !           267:        Page *outp;
        !           268: 
        !           269:        outp = *pg;
        !           270:        switch(type) {
        !           271:        case SG_TEXT:                                   /* Revert to demand load */
        !           272:                putpage(outp);
        !           273:                *pg = 0;
        !           274:                break;
        !           275: 
        !           276:        case SG_DATA:
        !           277:        case SG_BSS:
        !           278:        case SG_STACK:
        !           279:        case SG_SHARED:
        !           280:        case SG_SHDATA:
        !           281:                daddr = newswap();
        !           282:                cachedel(&swapimage, daddr);
        !           283:                lock(outp);
        !           284:                outp->ref++;
        !           285:                uncachepage(outp);
        !           286:                unlock(outp);
        !           287: 
        !           288:                /* Enter swap page into cache before segment is unlocked so that
        !           289:                 * a fault will cause a cache recovery rather than a pagein on a
        !           290:                 * partially written block.
        !           291:                 */
        !           292:                outp->daddr = daddr;
        !           293:                cachepage(outp, &swapimage);
        !           294:                *pg = (Page*)(daddr|PG_ONSWAP);
        !           295: 
        !           296:                /* Add me to IO transaction list */
        !           297:                iolist[ioptr++] = outp;
        !           298:        }
        !           299: }
        !           300: 
        !           301: void
        !           302: executeio(void)
        !           303: {
        !           304:        Page *out;
        !           305:        int i, n;
        !           306:        Chan *c;
        !           307:        char *kaddr;
        !           308:        KMap *k;
        !           309: 
        !           310:        c = swapimage.c;
        !           311: 
        !           312:        for(i = 0; i < ioptr; i++) {
        !           313:                out = iolist[i];
        !           314:                k = kmap(out);
        !           315:                kaddr = (char*)VA(k);
        !           316: 
        !           317:                if(waserror())
        !           318:                        panic("executeio: page out I/O error");
        !           319: 
        !           320:                n = (*devtab[c->type].write)(c, kaddr, BY2PG, out->daddr);
        !           321:                if(n != BY2PG)
        !           322:                        nexterror();
        !           323: 
        !           324:                kunmap(k);
        !           325:                poperror();
        !           326: 
        !           327:                /* Free up the page after I/O */
        !           328:                lock(out);
        !           329:                out->ref--;
        !           330:                unlock(out);
        !           331:                putpage(out);
        !           332:        }
        !           333:        ioptr = 0;
        !           334: }
        !           335: 
        !           336: int
        !           337: needpages(void *p)
        !           338: {
        !           339:        USED(p);
        !           340:        return palloc.freecount < swapalloc.headroom;
        !           341: }
        !           342: 
        !           343: void
        !           344: setswapchan(Chan *c)
        !           345: {
        !           346:        if(swapimage.c) {
        !           347:                if(swapalloc.free != conf.nswap)
        !           348:                        error(Einuse);
        !           349:                close(swapimage.c);
        !           350:        }
        !           351:        incref(c);
        !           352:        swapimage.c = c;
        !           353: }

unix.superglobalmegacorp.com

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