Annotation of lucent/sys/src/9/port/page.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: #define        pghash(daddr)   palloc.hash[(daddr>>PGSHIFT)&(PGHSIZE-1)]
                      9: 
                     10: static Lock pglock;
                     11: struct Palloc palloc;
                     12: 
                     13: void
                     14: pageinit(void)
                     15: {
                     16:        Page *p;
                     17:        ulong np, hw, hr, vmem, pmem;
                     18: 
                     19:        np = palloc.np0+palloc.np1;
                     20:        palloc.head = xalloc(np*sizeof(Page));
                     21:        if(palloc.head == 0)
                     22:                panic("pageinit");
                     23: 
                     24:        p = palloc.head;
                     25:        while(palloc.np0 > 0) {
                     26:                p->prev = p-1;
                     27:                p->next = p+1;
                     28:                p->pa = palloc.p0;
                     29:                palloc.p0 += BY2PG;
                     30:                palloc.np0--;
                     31:                p++;
                     32:        }
                     33:        while(palloc.np1 > 0) {
                     34:                p->prev = p-1;
                     35:                p->next = p+1;
                     36:                p->pa = palloc.p1;
                     37:                palloc.p1 += BY2PG;
                     38:                palloc.np1--;
                     39:                p++;
                     40:        }
                     41:        palloc.tail = p - 1;
                     42:        palloc.head->prev = 0;
                     43:        palloc.tail->next = 0;
                     44: 
                     45:        palloc.user = p - palloc.head;
                     46:        palloc.freecount = palloc.user;
                     47:        pmem = palloc.user*BY2PG/1024;
                     48:        vmem = pmem + (conf.nswap*BY2PG)/1024;
                     49: 
                     50:        /* Pageing numbers */
                     51:        swapalloc.highwater = (palloc.freecount*5)/100;
                     52:        swapalloc.headroom = swapalloc.highwater + (swapalloc.highwater/4);
                     53: 
                     54:        hw = swapalloc.highwater*BY2PG;
                     55:        hr = swapalloc.headroom*BY2PG;
                     56: 
                     57:        print("%lud free pages, %dK bytes, swap %dK, highwater %dK, headroom %dK\n", 
                     58:        palloc.user, pmem, vmem, hw/1024, hr/1024);/**/
                     59: }
                     60: 
                     61: Page*
                     62: newpage(int clear, Segment **s, ulong va)
                     63: {
                     64:        Page *p;
                     65:        KMap *k;
                     66:        int hw, i, dontalloc;
                     67: 
                     68: retry:
                     69:        lock(&palloc);
                     70: 
                     71:        hw = swapalloc.highwater;
                     72:        while((palloc.freecount < hw && u->p->kp == 0) || palloc.freecount == 0) {
                     73:                palloc.wanted++;
                     74:                unlock(&palloc);
                     75:                dontalloc = 0;
                     76:                if(s && *s) {
                     77:                        qunlock(&((*s)->lk));
                     78:                        *s = 0;
                     79:                        dontalloc = 1;
                     80:                }
                     81:                qlock(&palloc.pwait);                   /* Hold memory requesters here */
                     82: 
                     83:                while(waserror())                       /* Ignore interrupts */
                     84:                        ;
                     85: 
                     86:                kickpager();
                     87:                tsleep(&palloc.r, ispages, 0, 1000);
                     88: 
                     89:                poperror();
                     90: 
                     91:                qunlock(&palloc.pwait);
                     92: 
                     93:                /*
                     94:                 * If called from fault and we lost the segment from underneath
                     95:                 * don't waste time allocating and freeing a page. Fault will call
                     96:                 * newpage again when it has reacquired the segment locks
                     97:                 */
                     98:                if(dontalloc)
                     99:                        return 0;
                    100: 
                    101:                lock(&palloc);
                    102:                palloc.wanted--;
                    103:        }
                    104: 
                    105:        p = palloc.head;
                    106:        if(palloc.head = p->next)               /* = Assign */
                    107:                palloc.head->prev = 0;
                    108:        else
                    109:                palloc.tail = 0;
                    110: 
                    111:        palloc.freecount--;
                    112:        unlock(&palloc);
                    113: 
                    114:        lock(p);
                    115:        if(p->ref != 0) {       /* lookpage has priority on steal */
                    116:                unlock(p);
                    117:                goto retry;
                    118:        }
                    119:        uncachepage(p);
                    120:        p->ref++;
                    121:        p->va = va;
                    122:        p->modref = 0;
                    123:        for(i = 0; i < MAXMACH; i++)
                    124:                p->cachectl[i] = PG_NOFLUSH;
                    125:        mmunewpage(p);
                    126:        unlock(p);
                    127: 
                    128:        if(clear){
                    129:                k = kmap(p);
                    130:                memset((void*)VA(k), 0, BY2PG);
                    131:                kunmap(k);
                    132:        }
                    133: 
                    134:        return p;
                    135: }
                    136: 
                    137: int
                    138: ispages(void *p)
                    139: {
                    140:        USED(p);
                    141:        return palloc.freecount >= swapalloc.highwater;
                    142: }
                    143: 
                    144: void
                    145: putpage(Page *p)
                    146: {
                    147:        if(onswap(p)) {
                    148:                putswap(p);
                    149:                return;
                    150:        }
                    151: 
                    152:        lock(p);
                    153:        if(--p->ref == 0) {
                    154:                lock(&palloc);
                    155:                if(p->image && p->image != &swapimage) {
                    156:                        if(palloc.tail) {
                    157:                                p->prev = palloc.tail;
                    158:                                palloc.tail->next = p;
                    159:                        }
                    160:                        else {
                    161:                                palloc.head = p;
                    162:                                p->prev = 0;
                    163:                        }
                    164:                        palloc.tail = p;
                    165:                        p->next = 0;
                    166:                }
                    167:                else {
                    168:                        if(palloc.head) {
                    169:                                p->next = palloc.head;
                    170:                                palloc.head->prev = p;
                    171:                        }
                    172:                        else {
                    173:                                palloc.tail = p;
                    174:                                p->next = 0;
                    175:                        }
                    176:                        palloc.head = p;
                    177:                        p->prev = 0;
                    178:                }
                    179: 
                    180:                palloc.freecount++;     /* Release people waiting for memory */
                    181:                if(palloc.r.p != 0)
                    182:                        wakeup(&palloc.r);
                    183:                unlock(&palloc);
                    184:        }
                    185:        unlock(p);
                    186: }
                    187: 
                    188: void
                    189: simpleputpage(Page *pg)                        /* Always call with palloc locked */
                    190: {
                    191:        if(pg->ref != 1)
                    192:                panic("simpleputpage");
                    193:        pg->ref = 0;
                    194:        palloc.freecount++;
                    195:        if(palloc.head == 0) {
                    196:                palloc.head = palloc.tail = pg;
                    197:                pg->prev = pg->next = 0;
                    198:                return;
                    199:        }
                    200:        pg->next = palloc.head;
                    201:        palloc.head->prev = pg;
                    202:        pg->prev = 0;
                    203:        palloc.head = pg;
                    204: }
                    205: 
                    206: void
                    207: duppage(Page *p)                               /* Always call with p locked */
                    208: {
                    209:        Page *np;
                    210: 
                    211:        /* No dup for swap pages */
                    212:        if(p->image == &swapimage) {
                    213:                uncachepage(p); 
                    214:                return;
                    215:        }
                    216: 
                    217:        lock(&palloc);
                    218:        /* No freelist cache when memory is very low */
                    219:        if(palloc.freecount < swapalloc.highwater) {
                    220:                unlock(&palloc);
                    221:                uncachepage(p); 
                    222:                return;
                    223:        }
                    224: 
                    225:        np = palloc.head;               /* Allocate a new page from freelist */
                    226:        if(palloc.head = np->next)      /* = Assign */
                    227:                palloc.head->prev = 0;
                    228:        else
                    229:                palloc.tail = 0;
                    230: 
                    231:        if(palloc.tail) {               /* Link back onto tail to give us lru */
                    232:                np->prev = palloc.tail;
                    233:                palloc.tail->next = np;
                    234:                np->next = 0;
                    235:                palloc.tail = np;
                    236:        }
                    237:        else {
                    238:                palloc.head = palloc.tail = np;
                    239:                np->prev = np->next = 0;
                    240:        }
                    241: 
                    242:        unlock(&palloc);
                    243: 
                    244:        lock(np);                               /* Cache the new version */
                    245:        if(np->ref != 0) {                      /* Stolen by lookpage */
                    246:                uncachepage(p);
                    247:                unlock(np);
                    248:                return;
                    249:        }
                    250:        
                    251:        uncachepage(np);
                    252:        np->va = p->va;
                    253:        np->daddr = p->daddr;
                    254:        mmunewpage(np);
                    255:        copypage(p, np);
                    256:        cachepage(np, p->image);
                    257:        unlock(np);
                    258:        uncachepage(p);
                    259: }
                    260: 
                    261: void
                    262: copypage(Page *f, Page *t)
                    263: {
                    264:        KMap *ks, *kd;
                    265: 
                    266:        ks = kmap(f);
                    267:        kd = kmap(t);
                    268:        memmove((void*)VA(kd), (void*)VA(ks), BY2PG);
                    269:        kunmap(ks);
                    270:        kunmap(kd);
                    271: }
                    272: 
                    273: void
                    274: uncachepage(Page *p)                   /* Always called with a locked page */
                    275: {
                    276:        Page **l, *f;
                    277: 
                    278:        if(p->image == 0)
                    279:                return;
                    280: 
                    281:        lock(&palloc.hashlock);
                    282:        l = &pghash(p->daddr);
                    283:        for(f = *l; f; f = f->hash) {
                    284:                if(f == p) {
                    285:                        *l = p->hash;
                    286:                        break;
                    287:                }
                    288:                l = &f->hash;
                    289:        }
                    290:        unlock(&palloc.hashlock);
                    291:        putimage(p->image);
                    292:        p->image = 0;
                    293: }
                    294: 
                    295: void
                    296: cachepage(Page *p, Image *i)
                    297: {
                    298:        Page **l;
                    299: 
                    300:        /* If this ever happens it should be fixed by calling
                    301:         * uncachepage instead of panic. I think there is a race
                    302:         * with pio in which this can happen. Calling uncachepage is
                    303:         * correct - I just wanted to see if we got here.
                    304:         */
                    305:        if(p->image)
                    306:                panic("cachepage");
                    307: 
                    308:        incref(i);
                    309:        lock(&palloc.hashlock);
                    310:        p->image = i;
                    311:        l = &pghash(p->daddr);
                    312:        p->hash = *l;
                    313:        *l = p;
                    314:        unlock(&palloc.hashlock);
                    315: }
                    316: 
                    317: void
                    318: cachedel(Image *i, ulong daddr)
                    319: {
                    320:        Page *f, **l;
                    321: 
                    322:        lock(&palloc.hashlock);
                    323:        l = &pghash(daddr);
                    324:        for(f = *l; f; f = f->hash) {
                    325:                if(f->image == i && f->daddr == daddr) {
                    326:                        *l = f->hash;
                    327:                        break;
                    328:                }
                    329:                l = &f->hash;
                    330:        }
                    331:        unlock(&palloc.hashlock);
                    332: }
                    333: 
                    334: Page *
                    335: lookpage(Image *i, ulong daddr)
                    336: {
                    337:        Page *f;
                    338: 
                    339:        lock(&palloc.hashlock);
                    340:        for(f = pghash(daddr); f; f = f->hash) {
                    341:                if(f->image == i && f->daddr == daddr) {
                    342:                        unlock(&palloc.hashlock);
                    343: 
                    344:                        lock(f);
                    345:                        if(f->image != i || f->daddr != daddr) {
                    346:                                unlock(f);
                    347:                                return 0;
                    348:                        }
                    349: 
                    350:                        lock(&palloc);
                    351:                        if(++f->ref == 1) {
                    352:                                if(f->prev) 
                    353:                                        f->prev->next = f->next;
                    354:                                else
                    355:                                        palloc.head = f->next;
                    356: 
                    357:                                if(f->next)
                    358:                                        f->next->prev = f->prev;
                    359:                                else
                    360:                                        palloc.tail = f->prev;
                    361:                                palloc.freecount--;
                    362:                        }
                    363:                        unlock(&palloc);
                    364: 
                    365:                        unlock(f);
                    366:                        return f;       
                    367:                }
                    368:        }
                    369:        unlock(&palloc.hashlock);
                    370:        return 0;
                    371: }
                    372: 
                    373: Pte*
                    374: ptecpy(Pte *old)
                    375: {
                    376:        Pte *new;
                    377:        Page **src, **dst;
                    378: 
                    379:        new = ptealloc();
                    380:        dst = &new->pages[old->first-old->pages];
                    381:        new->first = dst;
                    382:        for(src = old->first; src <= old->last; src++, dst++)
                    383:                if(*src) {
                    384:                        if(onswap(*src))
                    385:                                dupswap(*src);
                    386:                        else {
                    387:                                lock(*src);
                    388:                                (*src)->ref++;
                    389:                                unlock(*src);
                    390:                        }
                    391:                        new->last = dst;
                    392:                        *dst = *src;
                    393:                }
                    394: 
                    395:        return new;             
                    396: }
                    397: 
                    398: Pte*
                    399: ptealloc(void)
                    400: {
                    401:        Pte *new;
                    402: 
                    403:        new = smalloc(sizeof(Pte));
                    404:        new->first = &new->pages[PTEPERTAB];
                    405:        new->last = new->pages;
                    406:        return new;
                    407: }
                    408: 
                    409: void
                    410: freepte(Segment *s, Pte *p)
                    411: {
                    412:        int ref;
                    413:        Page *pt, **pg, **ptop;
                    414:        void (*fn)(Page*);
                    415: 
                    416:        switch(s->type&SG_TYPE) {
                    417:        case SG_PHYSICAL:
                    418:                fn = s->pseg->pgfree;
                    419:                ptop = &p->pages[PTEPERTAB];
                    420:                if(fn) {
                    421:                        for(pg = p->pages; pg < ptop; pg++) {
                    422:                                if(*pg == 0)
                    423:                                        continue;
                    424:                                (*fn)(*pg);
                    425:                                *pg = 0;
                    426:                        }
                    427:                        break;
                    428:                }
                    429:                for(pg = p->pages; pg < ptop; pg++) {
                    430:                        pt = *pg;
                    431:                        if(pt == 0) 
                    432:                                continue;
                    433:                        lock(pt);
                    434:                        ref = --pt->ref;
                    435:                        unlock(pt);
                    436:                        if(ref == 0)
                    437:                                free(pt);
                    438:                }
                    439:                break;
                    440:        default:
                    441:                for(pg = p->first; pg <= p->last; pg++)
                    442:                        if(*pg) {
                    443:                                putpage(*pg);
                    444:                                *pg = 0;
                    445:                        }
                    446:        }
                    447:        free(p);
                    448: }

unix.superglobalmegacorp.com

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