Annotation of lucent/sys/src/9/port/alloc.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       "error.h"
                      7: 
                      8: 
                      9: /*
                     10:  * Plan 9 has two kernel allocators, the x... routines provide a first
                     11:  * fit hole allocator which should be used for permanent or large structures.
                     12:  * Routines are provided to allocate aligned memory which does not cross
                     13:  * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is
                     14:  * a 2n bucket allocator which steals from the x routines. This should
                     15:  * be used for small frequently used structures.
                     16:  */
                     17: 
                     18: #define        nil             ((void*)0)
                     19: #define datoff         ((ulong)((Xhdr*)0)->data)
                     20: #define bdatoff                ((ulong)((Bucket*)0)->data)
                     21: 
                     22: enum
                     23: {
                     24:        Maxpow          = 18,
                     25:        CUTOFF          = 12,
                     26:        Nhole           = 128,
                     27:        Magichole       = 0xDeadBabe,
                     28:        Magic2n         = 0xFeedBeef,
                     29:        Spanlist        = 64,
                     30: 
                     31:        NTRACE          = 20,
                     32: };
                     33: 
                     34: typedef struct Hole Hole;
                     35: typedef struct Xalloc Xalloc;
                     36: typedef struct Xhdr Xhdr;
                     37: typedef struct Bucket Bucket;
                     38: typedef struct Arena Arena;
                     39: 
                     40: struct Hole
                     41: {
                     42:        ulong   addr;
                     43:        ulong   size;
                     44:        ulong   top;
                     45:        Hole    *link;
                     46: };
                     47: 
                     48: struct Xhdr
                     49: {
                     50:        ulong   size;
                     51:        ulong   magix;
                     52:        char    data[1];
                     53: };
                     54: 
                     55: struct Xalloc
                     56: {
                     57:        Lock;
                     58:        Hole    hole[Nhole];
                     59:        Hole    *flist;
                     60:        Hole    *table;
                     61: };
                     62: 
                     63: struct Bucket
                     64: {
                     65:        int     size;
                     66:        int     magic;
                     67:        Bucket  *next;
                     68:        ulong   pc;
                     69:        char    data[1];
                     70: };
                     71: 
                     72: struct Arena
                     73: {
                     74:        Lock;
                     75:        Bucket  *btab[Maxpow];
                     76:        int     nbuck[Maxpow];
                     77:        struct{
                     78:                ulong   pc;
                     79:                ulong   alloc;
                     80:                ulong   free;
                     81:        }       trace[NTRACE];
                     82:        QLock   rq;
                     83:        Rendez  r;
                     84: };
                     85: 
                     86: static Arena   arena;
                     87: static Xalloc  xlists;
                     88: 
                     89: void
                     90: xinit(void)
                     91: {
                     92:        Hole *h, *eh;
                     93:        int up, np0, np1;
                     94: 
                     95:        eh = &xlists.hole[Nhole-1];
                     96:        for(h = xlists.hole; h < eh; h++)
                     97:                h->link = h+1;
                     98: 
                     99:        xlists.flist = xlists.hole;
                    100: 
                    101:        up = conf.upages;
                    102:        np1 = up;
                    103:        if(np1 > conf.npage1)
                    104:                np1 = conf.npage1;
                    105: 
                    106:        palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG;
                    107:        conf.npage1 -= np1;
                    108:        xhole(conf.base1, conf.npage1*BY2PG);
                    109:        conf.npage1 = conf.base1+(conf.npage1*BY2PG);
                    110:        up -= np1;
                    111: 
                    112:        np0 = up;
                    113:        if(np0 > conf.npage0)
                    114:                np0 = conf.npage0;
                    115: 
                    116:        palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG;
                    117:        conf.npage0 -= np0;
                    118:        xhole(conf.base0, conf.npage0*BY2PG);
                    119:        conf.npage0 = conf.base0+(conf.npage0*BY2PG);
                    120: 
                    121:        palloc.np0 = np0;
                    122:        palloc.np1 = np1;
                    123:        /* Save the bounds of kernel alloc memory for kernel mmu mapping */
                    124:        conf.base0 = (ulong)KADDR(conf.base0);
                    125:        conf.base1 = (ulong)KADDR(conf.base1);
                    126:        conf.npage0 = (ulong)KADDR(conf.npage0);
                    127:        conf.npage1 = (ulong)KADDR(conf.npage1);
                    128: }
                    129: 
                    130: /*
                    131:  * NB. spanalloc memory will cause a panic if free'd
                    132:  */
                    133: void*
                    134: xspanalloc(ulong size, int align, ulong span)
                    135: {
                    136:        int i, j;
                    137:        ulong a, p, sinc;
                    138:        ulong ptr[Spanlist];
                    139: 
                    140:        sinc = size/8;
                    141:        span = ~(span-1);
                    142:        for(i = 0; i < Spanlist; i++) {
                    143:                p = (ulong)xalloc(size+align);
                    144:                if(p == 0)
                    145:                        break;
                    146: 
                    147:                a = p+align;
                    148:                a &= ~(align-1);
                    149:                if((a&span) == ((a+size)&span)) {
                    150:                        for(j = 0; j < i; j++)
                    151:                                if(ptr[j])
                    152:                                        xfree((void*)ptr[j]);
                    153: 
                    154:                        return (void*)a;
                    155:                }
                    156:                xfree((void*)p);
                    157:                ptr[i] = (ulong)xalloc(sinc);
                    158:        }
                    159:        USED(sinc);
                    160:        xsummary();
                    161:        panic("xspanalloc: %d %d %lux\n", size, align, span);   
                    162:        return 0;
                    163: }
                    164: 
                    165: void*
                    166: xalloc(ulong size)
                    167: {
                    168:        Xhdr *p;
                    169:        Hole *h, **l;
                    170: 
                    171:        size += BY2WD + sizeof(Xhdr);
                    172:        size &= ~(BY2WD-1);
                    173: 
                    174:        lock(&xlists);
                    175:        l = &xlists.table;
                    176:        for(h = *l; h; h = h->link) {
                    177:                if(h->size >= size) {
                    178:                        p = (Xhdr*)h->addr;
                    179:                        h->addr += size;
                    180:                        h->size -= size;
                    181:                        if(h->size == 0) {
                    182:                                *l = h->link;
                    183:                                h->link = xlists.flist;
                    184:                                xlists.flist = h;
                    185:                        }
                    186:                        unlock(&xlists);
                    187:                        p = KADDR(p);
                    188:                        memset(p, 0, size);
                    189:                        p->magix = Magichole;
                    190:                        p->size = size;
                    191:                        return p->data;
                    192:                }
                    193:                l = &h->link;
                    194:        }
                    195:        unlock(&xlists);
                    196:        return nil;
                    197: }
                    198: 
                    199: void
                    200: xfree(void *p)
                    201: {
                    202:        Xhdr *x;
                    203: 
                    204:        x = (Xhdr*)((ulong)p - datoff);
                    205:        if(x->magix != Magichole)
                    206:                panic("xfree");
                    207: 
                    208:        xhole(PADDR(x), x->size);
                    209: }
                    210: 
                    211: void
                    212: xhole(ulong addr, ulong size)
                    213: {
                    214:        ulong top;
                    215:        Hole *h, *c, **l;
                    216: 
                    217:        if(size == 0)
                    218:                return;
                    219: 
                    220:        top = addr + size;
                    221:        lock(&xlists);
                    222:        l = &xlists.table;
                    223:        for(h = *l; h; h = h->link) {
                    224:                if(h->top == addr) {
                    225:                        h->size += size;
                    226:                        h->top = h->addr+h->size;
                    227:                        c = h->link;
                    228:                        if(c && h->top == c->addr) {
                    229:                                h->top += c->size;
                    230:                                h->size += c->size;
                    231:                                h->link = c->link;
                    232:                                c->link = xlists.flist;
                    233:                                xlists.flist = c;
                    234:                        }
                    235:                        unlock(&xlists);
                    236:                        return;
                    237:                }
                    238:                if(h->addr > addr)
                    239:                        break;
                    240:                l = &h->link;
                    241:        }
                    242:        if(h && top == h->addr) {
                    243:                h->addr -= size;
                    244:                h->size += size;
                    245:                unlock(&xlists);
                    246:                return;
                    247:        }
                    248: 
                    249:        if(xlists.flist == nil) {
                    250:                unlock(&xlists);
                    251:                print("xfree: no free holes, leaked %d bytes\n", size);
                    252:                return;
                    253:        }
                    254: 
                    255:        h = xlists.flist;
                    256:        xlists.flist = h->link;
                    257:        h->addr = addr;
                    258:        h->top = top;
                    259:        h->size = size;
                    260:        h->link = *l;
                    261:        *l = h;
                    262:        unlock(&xlists);
                    263: }
                    264: 
                    265: void
                    266: alloctrace(void *p, ulong pc)
                    267: {
                    268:        Bucket *bp;
                    269:        int i;
                    270: 
                    271:        bp = (Bucket*)((ulong)p - bdatoff);
                    272:        if(bp->size != 13)
                    273:                return;
                    274:        bp->pc = pc;
                    275:        lock(&arena);
                    276:        for(i = 0; i < NTRACE; i++){
                    277:                if(arena.trace[i].pc == 0)
                    278:                        arena.trace[i].pc = pc;
                    279:                if(arena.trace[i].pc == pc){
                    280:                        arena.trace[i].alloc++;
                    281:                        break;
                    282:                }
                    283:        }
                    284:        unlock(&arena);
                    285: }
                    286: 
                    287: void*
                    288: malloc(ulong size)
                    289: {
                    290:        ulong next;
                    291:        int pow, n;
                    292:        Bucket *bp, *nbp;
                    293: 
                    294:        for(pow = 3; pow < Maxpow; pow++)
                    295:                if(size <= (1<<pow))
                    296:                        goto good;
                    297: 
                    298:        return nil;
                    299: good:
                    300:        /* Allocate off this list */
                    301:        lock(&arena);
                    302:        bp = arena.btab[pow];
                    303:        if(bp) {
                    304:                arena.btab[pow] = bp->next;
                    305:                if(bp->magic != 0 || bp->size != pow){
                    306:                        unlock(&arena);
                    307:                        panic("malloc bp %lux magic %lux size %d next %lux pow %d", bp,
                    308:                                bp->magic, bp->size, bp->next, pow);
                    309:                }
                    310:                bp->magic = Magic2n;
                    311:                unlock(&arena);
                    312: 
                    313:                memset(bp->data, 0, size);
                    314:                bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
                    315:                return  bp->data;
                    316:        }
                    317:        unlock(&arena);
                    318: 
                    319:        size = sizeof(Bucket)+(1<<pow);
                    320:        size += 3;
                    321:        size &= ~3;
                    322: 
                    323:        if(pow < CUTOFF) {
                    324:                n = (CUTOFF-pow)+2;
                    325:                bp = xalloc(size*n);
                    326:                if(bp == nil)
                    327:                        return nil;
                    328: 
                    329:                nbp = bp;
                    330:                lock(&arena);
                    331:                arena.nbuck[pow] += n;
                    332:                while(--n) {
                    333:                        next = (ulong)nbp+size;
                    334:                        nbp = (Bucket*)next;
                    335:                        nbp->size = pow;
                    336:                        nbp->next = arena.btab[pow];
                    337:                        arena.btab[pow] = nbp;
                    338:                }
                    339:                unlock(&arena);
                    340:        }
                    341:        else {
                    342:                bp = xalloc(size);
                    343:                if(bp == nil)
                    344:                        return nil;
                    345: 
                    346:                arena.nbuck[pow]++;
                    347:        }
                    348: 
                    349:        bp->size = pow;
                    350:        bp->magic = Magic2n;
                    351:        bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
                    352:        return bp->data;
                    353: }
                    354: 
                    355: void*
                    356: smalloc(ulong size)
                    357: {
                    358:        char *s;
                    359:        void *p;
                    360:        int attempt;
                    361:        Bucket *bp;
                    362: 
                    363:        for(attempt = 0; attempt < 1000; attempt++) {
                    364:                p = malloc(size);
                    365:                if(p != nil) {
                    366:                        bp = (Bucket*)((ulong)p - bdatoff);
                    367:                        bp->pc = getcallerpc(((uchar*)&size) - sizeof(size));
                    368:                        return p;
                    369:                }
                    370:                s = u->p->psstate;
                    371:                u->p->psstate = "Malloc";
                    372:                qlock(&arena.rq);
                    373:                while(waserror())
                    374:                        ;
                    375:                sleep(&arena.r, return0, nil);
                    376:                poperror();
                    377:                qunlock(&arena.rq);
                    378:                u->p->psstate = s;
                    379:        }
                    380:        print("%s:%d: out of memory in smalloc %d\n", u->p->text, u->p->pid, size);
                    381:        u->p->state = Broken;
                    382:        u->p->psstate = "NoMem";
                    383:        for(;;)
                    384:                sched();
                    385:        return 0;
                    386: }
                    387: 
                    388: int
                    389: msize(void *ptr)
                    390: {
                    391:        Bucket *bp;
                    392: 
                    393:        bp = (Bucket*)((ulong)ptr - bdatoff);
                    394:        if(bp->magic != Magic2n)
                    395:                panic("msize");
                    396:        return 1<<bp->size;
                    397: }
                    398: 
                    399: void
                    400: free(void *ptr)
                    401: {
                    402:        ulong pc, n;
                    403:        Bucket *bp, **l;
                    404: 
                    405:        bp = (Bucket*)((ulong)ptr - bdatoff);
                    406:        l = &arena.btab[bp->size];
                    407: 
                    408:        lock(&arena);
                    409:        if(bp->magic != Magic2n)
                    410:                panic("free");
                    411:        bp->magic = 0;
                    412:        bp->next = *l;
                    413:        *l = bp;
                    414:        if(bp->size == 13) {
                    415:                pc = bp->pc;
                    416:                for(n = 0; n < NTRACE; n++){
                    417:                        if(arena.trace[n].pc == pc){
                    418:                                arena.trace[n].free++;
                    419:                                break;
                    420:                        }
                    421:                }
                    422:        }
                    423:        unlock(&arena);
                    424:        if(arena.r.p)
                    425:                wakeup(&arena.r);
                    426: }
                    427: 
                    428: void
                    429: xsummary(void)
                    430: {
                    431:        Hole *h;
                    432:        Bucket *k;
                    433:        int i, nfree, nused;
                    434: 
                    435:        i = 0;
                    436:        for(h = xlists.flist; h; h = h->link)
                    437:                i++;
                    438: 
                    439:        print("%d holes free\n", i);
                    440:        i = 0;
                    441:        for(h = xlists.table; h; h = h->link) {
                    442:                print("%.8lux %.8lux %d\n", h->addr, h->top, h->size);
                    443:                i += h->size;
                    444:        }
                    445:        print("%d bytes free\n", i);
                    446:        nused = 0;
                    447:        for(i = 3; i < Maxpow; i++) {
                    448:                if(arena.btab[i] == 0 && arena.nbuck[i] == 0)
                    449:                        continue;
                    450:                nused += arena.nbuck[i]*(1<<i);
                    451:                nfree = 0;
                    452:                for(k = arena.btab[i]; k; k = k->next)
                    453:                        nfree++;
                    454:                print("%8d %4d %4d\n", 1<<i, arena.nbuck[i], nfree);
                    455:        }
                    456:        for(i = 0; i < NTRACE && arena.trace[i].pc; i++)
                    457:                print("%lux %d %d\n", arena.trace[i].pc, arena.trace[i].alloc, arena.trace[i].free);
                    458:        print("%d bytes in pool\n", nused);
                    459: }

unix.superglobalmegacorp.com

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