Annotation of lucent/sys/src/9/port/segment.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: Page *lkpage(Segment*, ulong);
                      9: void lkpgfree(Page*);
                     10: void imagereclaim(void);
                     11: 
                     12: /* System specific segattach devices */
                     13: #include "io.h"
                     14: #include "segment.h"
                     15: 
                     16: #define IHASHSIZE      64
                     17: #define ihash(s)       imagealloc.hash[s%IHASHSIZE]
                     18: struct
                     19: {
                     20:        Lock;
                     21:        Image   *free;
                     22:        Image   *hash[IHASHSIZE];
                     23:        QLock   ireclaim;
                     24: }imagealloc;
                     25: 
                     26: void
                     27: initseg(void)
                     28: {
                     29:        Image *i, *ie;
                     30: 
                     31:        imagealloc.free = xalloc(conf.nimage*sizeof(Image));
                     32:        ie = &imagealloc.free[conf.nimage-1];
                     33:        for(i = imagealloc.free; i < ie; i++)
                     34:                i->next = i+1;
                     35:        i->next = 0;
                     36: }
                     37: 
                     38: Segment *
                     39: newseg(int type, ulong base, ulong size)
                     40: {
                     41:        Segment *s;
                     42: 
                     43:        if(size > (SEGMAPSIZE*PTEPERTAB))
                     44:                error(Enovmem);
                     45: 
                     46:        s = smalloc(sizeof(Segment));
                     47:        s->ref = 1;
                     48:        s->type = type;
                     49:        s->base = base;
                     50:        s->top = base+(size*BY2PG);
                     51:        s->size = size;
                     52:        return s;
                     53: }
                     54: 
                     55: void
                     56: putseg(Segment *s)
                     57: {
                     58:        Pte **pp, **emap;
                     59:        Image *i;
                     60: 
                     61:        if(s == 0)
                     62:                return;
                     63: 
                     64:        i = s->image;
                     65:        if(i != 0) {
                     66:                lock(i);
                     67:                lock(s);
                     68:                if(i->s == s && s->ref == 1)
                     69:                        i->s = 0;
                     70:                unlock(i);
                     71:        }
                     72:        else
                     73:                lock(s);
                     74: 
                     75:        s->ref--;
                     76:        if(s->ref != 0) {
                     77:                unlock(s);
                     78:                return;
                     79:        }
                     80: 
                     81:        qlock(&s->lk);
                     82:        if(i)
                     83:                putimage(i);
                     84: 
                     85:        emap = &s->map[SEGMAPSIZE];
                     86:        for(pp = s->map; pp < emap; pp++)
                     87:                if(*pp)
                     88:                        freepte(s, *pp);
                     89: 
                     90:        qunlock(&s->lk);
                     91:        free(s);
                     92: }
                     93: 
                     94: void
                     95: relocateseg(Segment *s, ulong offset)
                     96: {
                     97:        Pte **p, **endpte;
                     98:        Page **pg, **endpages;
                     99: 
                    100:        endpte = &s->map[SEGMAPSIZE];
                    101:        for(p = s->map; p < endpte; p++) {
                    102:                if(*p) {
                    103:                        endpages = &((*p)->pages[PTEPERTAB]);
                    104:                        for(pg = (*p)->pages; pg < endpages; pg++)
                    105:                                if(*pg)
                    106:                                        (*pg)->va += offset;
                    107:                }
                    108:        }
                    109: }
                    110: 
                    111: Segment*
                    112: dupseg(Segment **seg, int segno, int share)
                    113: {
                    114:        int i;
                    115:        Pte *pte;
                    116:        Segment *n, *s;
                    117: 
                    118:        SET(n);
                    119:        s = seg[segno];
                    120: 
                    121:        switch(s->type&SG_TYPE) {
                    122:        case SG_TEXT:                   /* New segment shares pte set */
                    123:        case SG_SHARED:
                    124:        case SG_PHYSICAL:
                    125:        case SG_SHDATA:
                    126:                incref(s);
                    127:                return s;
                    128: 
                    129:        case SG_STACK:
                    130:                qlock(&s->lk);
                    131:                n = newseg(s->type, s->base, s->size);
                    132:                break;
                    133: 
                    134:        case SG_BSS:                    /* Just copy on write */
                    135:                qlock(&s->lk);
                    136:                if(share && s->ref == 1) {
                    137:                        s->type = (s->type&~SG_TYPE)|SG_SHARED;
                    138:                        incref(s);
                    139:                        qunlock(&s->lk);
                    140:                        return s;
                    141:                }
                    142:                n = newseg(s->type, s->base, s->size);
                    143:                break;
                    144: 
                    145:        case SG_DATA:                   /* Copy on write plus demand load info */
                    146:                if(segno == TSEG)
                    147:                        return data2txt(s);
                    148: 
                    149:                qlock(&s->lk);
                    150:                if(share && s->ref == 1) {
                    151:                        s->type = (s->type&~SG_TYPE)|SG_SHDATA;
                    152:                        incref(s);
                    153:                        qunlock(&s->lk);
                    154:                        return s;
                    155:                }
                    156:                n = newseg(s->type, s->base, s->size);
                    157: 
                    158:                incref(s->image);
                    159:                n->image = s->image;
                    160:                n->fstart = s->fstart;
                    161:                n->flen = s->flen;
                    162:                break;
                    163:        }
                    164:        for(i = 0; i < SEGMAPSIZE; i++)
                    165:                if(pte = s->map[i])
                    166:                        n->map[i] = ptecpy(pte);
                    167: 
                    168:        n->flushme = s->flushme;
                    169:        qunlock(&s->lk);
                    170:        return n;       
                    171: }
                    172: 
                    173: void
                    174: segpage(Segment *s, Page *p)
                    175: {
                    176:        Pte **pte;
                    177:        ulong off;
                    178:        Page **pg;
                    179: 
                    180:        if(p->va < s->base || p->va >= s->top)
                    181:                panic("segpage");
                    182: 
                    183:        off = p->va - s->base;
                    184:        pte = &s->map[off/PTEMAPMEM];
                    185:        if(*pte == 0)
                    186:                *pte = ptealloc();
                    187: 
                    188:        pg = &(*pte)->pages[(off&(PTEMAPMEM-1))/BY2PG];
                    189:        *pg = p;
                    190:        if(pg < (*pte)->first)
                    191:                (*pte)->first = pg;
                    192:        if(pg > (*pte)->last)
                    193:                (*pte)->last = pg;
                    194: }
                    195: 
                    196: Image*
                    197: attachimage(int type, Chan *c, ulong base, ulong len)
                    198: {
                    199:        Image *i, **l;
                    200: 
                    201:        lock(&imagealloc);
                    202: 
                    203:        /*
                    204:         * Search the image cache for remains of the text from a previous 
                    205:         * or currently running incarnation 
                    206:         */
                    207:        for(i = ihash(c->qid.path); i; i = i->hash) {
                    208:                if(c->qid.path == i->qid.path) {
                    209:                        lock(i);
                    210:                        if(eqqid(c->qid, i->qid) &&
                    211:                           eqqid(c->mqid, i->mqid) &&
                    212:                           c->mchan == i->mchan &&
                    213:                           c->type == i->type) {
                    214:                                i->ref++;
                    215:                                goto found;
                    216:                        }
                    217:                        unlock(i);
                    218:                }
                    219:        }
                    220:        
                    221:        /*
                    222:         * imagereclaim dumps pages from the free list which are cached by image
                    223:         * structures. This should free some image structures.
                    224:         */
                    225:        while(!(i = imagealloc.free)) {
                    226:                unlock(&imagealloc);
                    227:                imagereclaim();
                    228:                resrcwait(0);
                    229:                lock(&imagealloc);
                    230:        }
                    231: 
                    232:        imagealloc.free = i->next;
                    233: 
                    234:        lock(i);
                    235:        incref(c);
                    236:        i->c = c;
                    237:        i->type = c->type;
                    238:        i->qid = c->qid;
                    239:        i->mqid = c->mqid;
                    240:        i->mchan = c->mchan;
                    241:        i->ref = 1;
                    242:        l = &ihash(c->qid.path);
                    243:        i->hash = *l;
                    244:        *l = i;
                    245: found:
                    246:        unlock(&imagealloc);
                    247: 
                    248:        if(i->s == 0) {
                    249:                /* Disaster after commit in exec */
                    250:                if(waserror()) {
                    251:                        unlock(i);
                    252:                        pexit(Enovmem, 1);
                    253:                }
                    254:                i->s = newseg(type, base, len);
                    255:                i->s->image = i;
                    256:                poperror();
                    257:        }
                    258:        else
                    259:                incref(i->s);
                    260: 
                    261:        return i;
                    262: }
                    263: 
                    264: void
                    265: imagereclaim(void)
                    266: {
                    267:        Page *p;
                    268: 
                    269:        /* Somebody is already cleaning the page cache */
                    270:        if(!canqlock(&imagealloc.ireclaim))
                    271:                return;
                    272: 
                    273:        lock(&palloc);
                    274:        for(p = palloc.head; p; p = p->next) {
                    275:                if(p->image && p->ref == 0 && p->image != &swapimage && canlock(p)) {
                    276:                        if(p->ref == 0)
                    277:                                uncachepage(p);
                    278:                        unlock(p);
                    279:                }
                    280:        }
                    281:        unlock(&palloc);
                    282:        qunlock(&imagealloc.ireclaim);
                    283: }
                    284: 
                    285: void
                    286: putimage(Image *i)
                    287: {
                    288:        Chan *c;
                    289:        Image *f, **l;
                    290: 
                    291:        if(i == &swapimage)
                    292:                return;
                    293: 
                    294:        lock(i);
                    295:        if(--i->ref == 0) {
                    296:                l = &ihash(i->qid.path);
                    297:                i->qid = (Qid){~0, ~0}; 
                    298:                unlock(i);
                    299:                c = i->c;
                    300:        
                    301:                lock(&imagealloc);
                    302:                for(f = *l; f; f = f->hash) {
                    303:                        if(f == i) {
                    304:                                *l = i->hash;
                    305:                                break;
                    306:                        }
                    307:                        l = &f->hash;
                    308:                }
                    309: 
                    310:                i->next = imagealloc.free;
                    311:                imagealloc.free = i;
                    312:                unlock(&imagealloc);
                    313: 
                    314:                close(c);
                    315:                return;
                    316:        }
                    317:        unlock(i);
                    318: }
                    319: 
                    320: long
                    321: ibrk(ulong addr, int seg)
                    322: {
                    323:        Segment *s, *ns;
                    324:        ulong newtop, newsize;
                    325:        int i;
                    326: 
                    327:        s = u->p->seg[seg];
                    328:        if(s == 0)
                    329:                error(Ebadarg);
                    330: 
                    331:        if(addr == 0)
                    332:                return s->base;
                    333: 
                    334:        qlock(&s->lk);
                    335: 
                    336:        /* We may start with the bss overlapping the data */
                    337:        if(addr < s->base) {
                    338:                if(seg != BSEG || u->p->seg[DSEG] == 0 || addr < u->p->seg[DSEG]->base) {
                    339:                        qunlock(&s->lk);
                    340:                        error(Enovmem);
                    341:                }
                    342:                addr = s->base;
                    343:        }
                    344:                
                    345:        newtop = PGROUND(addr);
                    346:        newsize = (newtop-s->base)/BY2PG;
                    347:        if(newtop < s->top) {
                    348:                mfreeseg(s, newtop, (s->top-newtop)/BY2PG);
                    349:                qunlock(&s->lk);
                    350:                flushmmu();
                    351:                return 0;
                    352:        }
                    353: 
                    354:        for(i = 0; i < NSEG; i++) {
                    355:                ns = u->p->seg[i];
                    356:                if(ns == 0 || ns == s)
                    357:                        continue;
                    358:                if(newtop >= ns->base && newtop < ns->top) {
                    359:                        qunlock(&s->lk);
                    360:                        error(Esoverlap);
                    361:                }
                    362:        }
                    363: 
                    364:        if(newsize > (PTEMAPMEM*SEGMAPSIZE)/BY2PG) {
                    365:                qunlock(&s->lk);
                    366:                error(Enovmem);
                    367:        }
                    368: 
                    369:        s->top = newtop;
                    370:        s->size = newsize;
                    371:        qunlock(&s->lk);
                    372:        return 0;
                    373: }
                    374: 
                    375: void
                    376: mfreeseg(Segment *s, ulong start, int pages)
                    377: {
                    378:        int i, j;
                    379:        ulong soff;
                    380:        Page *pg;
                    381: 
                    382:        soff = start-s->base;
                    383:        j = (soff&(PTEMAPMEM-1))/BY2PG;
                    384: 
                    385:        for(i = soff/PTEMAPMEM; i < SEGMAPSIZE; i++) {
                    386:                if(pages <= 0) 
                    387:                        break;
                    388:                if(s->map[i] == 0) {
                    389:                        pages -= PTEPERTAB-j;
                    390:                        j = 0;
                    391:                        continue;
                    392:                }
                    393:                while(j < PTEPERTAB) {
                    394:                        pg = s->map[i]->pages[j];
                    395:                        if(pg) {
                    396:                                putpage(pg);
                    397:                                s->map[i]->pages[j] = 0;        
                    398:                        }
                    399:                        if(--pages == 0)
                    400:                                return;
                    401:                        j++;
                    402:                }
                    403:                j = 0;
                    404:        }
                    405: }
                    406: 
                    407: int
                    408: isoverlap(ulong va, int len)
                    409: {
                    410:        int i;
                    411:        Segment *ns;
                    412:        ulong newtop;
                    413: 
                    414:        newtop = va+len;
                    415:        for(i = 0; i < NSEG; i++) {
                    416:                ns = u->p->seg[i];
                    417:                if(ns == 0)
                    418:                        continue;       
                    419:                if((newtop > ns->base && newtop <= ns->top) ||
                    420:                   (va >= ns->base && va < ns->top))
                    421:                        return 1;
                    422:        }
                    423:        return 0;
                    424: }
                    425: 
                    426: ulong
                    427: segattach(Proc *p, ulong attr, char *name, ulong va, ulong len)
                    428: {
                    429:        int i, sno;
                    430:        Segment *s;
                    431:        Physseg *ps;
                    432: 
                    433:        USED(p);
                    434:        if(va != 0 && (va&KZERO) == KZERO)      /* BUG: Only ok for now */
                    435:                error(Ebadarg);
                    436: 
                    437:        validaddr((ulong)name, 1, 0);
                    438:        vmemchr(name, 0, ~0);
                    439: 
                    440:        for(sno = 0; sno < NSEG; sno++)
                    441:                if(u->p->seg[sno] == 0 && sno != ESEG)
                    442:                        break;
                    443: 
                    444:        if(sno == NSEG)
                    445:                error(Enovmem);
                    446: 
                    447:        len = PGROUND(len);
                    448: 
                    449:        /* Find a hole in the address space */
                    450:        if(va == 0) {
                    451:                va = p->seg[SSEG]->base - len;
                    452:                for(i = 0; i < 20; i++) {
                    453:                        if(isoverlap(va, len) == 0)
                    454:                                break;
                    455:                        va -= len;
                    456:                }
                    457:        }
                    458: 
                    459:        va = va&~(BY2PG-1);
                    460:        if(isoverlap(va, len))
                    461:                error(Esoverlap);
                    462: 
                    463:        for(ps = physseg; ps->name; ps++)
                    464:                if(strcmp(name, ps->name) == 0)
                    465:                        goto found;
                    466: 
                    467:        error(Ebadarg);
                    468: found:
                    469:        if(len > ps->size)
                    470:                error(Enovmem);
                    471: 
                    472:        attr &= ~SG_TYPE;               /* Turn off what we are not allowed */
                    473:        attr |= ps->attr;               /* Copy in defaults */
                    474: 
                    475:        s = newseg(attr, va, len/BY2PG);
                    476:        s->pseg = ps;
                    477:        u->p->seg[sno] = s;
                    478: 
                    479:        return va;
                    480: }
                    481: 
                    482: void
                    483: pteflush(Pte *pte, int s, int e)
                    484: {
                    485:        int i;
                    486:        Page *p;
                    487: 
                    488:        for(i = s; i < e; i++) {
                    489:                p = pte->pages[i];
                    490:                if(pagedout(p) == 0)
                    491:                        memset(p->cachectl, PG_TXTFLUSH, sizeof(p->cachectl));
                    492:        }
                    493: }
                    494: 
                    495: 
                    496: long
                    497: syssegflush(ulong *arg)
                    498: {      Segment *s;
                    499:        ulong addr, l;
                    500:        Pte *pte;
                    501:        int chunk, ps, pe, len;
                    502: 
                    503:        addr = arg[0];
                    504:        len = arg[1];
                    505: 
                    506:        while(len > 0) {
                    507:                s = seg(u->p, addr, 1);
                    508:                if(s == 0)
                    509:                        error(Ebadarg);
                    510: 
                    511:                s->flushme = 1;
                    512:        more:
                    513:                l = len;
                    514:                if(addr+l > s->top)
                    515:                        l = s->top - addr;
                    516: 
                    517:                ps = addr-s->base;
                    518:                pte = s->map[ps/PTEMAPMEM];
                    519:                ps &= PTEMAPMEM-1;
                    520:                pe = PTEMAPMEM;
                    521:                if(pe-ps > l){
                    522:                        pe = ps + l;
                    523:                        pe = (pe+BY2PG-1)&~(BY2PG-1);
                    524:                }
                    525:                if(pe == ps) {
                    526:                        qunlock(&s->lk);
                    527:                        error(Ebadarg);
                    528:                }
                    529: 
                    530:                if(pte)
                    531:                        pteflush(pte, ps/BY2PG, pe/BY2PG);
                    532: 
                    533:                chunk = pe-ps;
                    534:                len -= chunk;
                    535:                addr += chunk;
                    536: 
                    537:                if(len > 0 && addr < s->top)
                    538:                        goto more;
                    539: 
                    540:                qunlock(&s->lk);
                    541:        }
                    542:        flushmmu();
                    543:        return 0;
                    544: }

unix.superglobalmegacorp.com

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