Annotation of lucent/sys/src/9/port/segment.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: 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.