Annotation of lucent/sys/src/9/port/swap.c, revision 1.1.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.