13e12c5d1SDavid du Colombier #include "u.h" 23e12c5d1SDavid du Colombier #include "../port/lib.h" 33e12c5d1SDavid du Colombier #include "mem.h" 43e12c5d1SDavid du Colombier #include "dat.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier #include "error.h" 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier /* 103e12c5d1SDavid du Colombier * Plan 9 has two kernel allocators, the x... routines provide a first 113e12c5d1SDavid du Colombier * fit hole allocator which should be used for permanent or large structures. 123e12c5d1SDavid du Colombier * Routines are provided to allocate aligned memory which does not cross 133e12c5d1SDavid du Colombier * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is 143e12c5d1SDavid du Colombier * a 2n bucket allocator which steals from the x routines. This should 153e12c5d1SDavid du Colombier * be used for small frequently used structures. 163e12c5d1SDavid du Colombier */ 173e12c5d1SDavid du Colombier 183e12c5d1SDavid du Colombier #define nil ((void*)0) 193e12c5d1SDavid du Colombier #define datoff ((ulong)((Xhdr*)0)->data) 203e12c5d1SDavid du Colombier #define bdatoff ((ulong)((Bucket*)0)->data) 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier enum 233e12c5d1SDavid du Colombier { 243e12c5d1SDavid du Colombier Maxpow = 18, 253e12c5d1SDavid du Colombier CUTOFF = 12, 263e12c5d1SDavid du Colombier Nhole = 128, 273e12c5d1SDavid du Colombier Magichole = 0xDeadBabe, 283e12c5d1SDavid du Colombier Magic2n = 0xFeedBeef, 293e12c5d1SDavid du Colombier Spanlist = 64, 30*219b2ee8SDavid du Colombier 31*219b2ee8SDavid du Colombier NTRACE = 20, 323e12c5d1SDavid du Colombier }; 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier typedef struct Hole Hole; 353e12c5d1SDavid du Colombier typedef struct Xalloc Xalloc; 363e12c5d1SDavid du Colombier typedef struct Xhdr Xhdr; 373e12c5d1SDavid du Colombier typedef struct Bucket Bucket; 383e12c5d1SDavid du Colombier typedef struct Arena Arena; 393e12c5d1SDavid du Colombier 403e12c5d1SDavid du Colombier struct Hole 413e12c5d1SDavid du Colombier { 423e12c5d1SDavid du Colombier ulong addr; 433e12c5d1SDavid du Colombier ulong size; 443e12c5d1SDavid du Colombier ulong top; 453e12c5d1SDavid du Colombier Hole *link; 463e12c5d1SDavid du Colombier }; 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier struct Xhdr 493e12c5d1SDavid du Colombier { 503e12c5d1SDavid du Colombier ulong size; 513e12c5d1SDavid du Colombier ulong magix; 523e12c5d1SDavid du Colombier char data[1]; 533e12c5d1SDavid du Colombier }; 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier struct Xalloc 563e12c5d1SDavid du Colombier { 573e12c5d1SDavid du Colombier Lock; 583e12c5d1SDavid du Colombier Hole hole[Nhole]; 593e12c5d1SDavid du Colombier Hole *flist; 603e12c5d1SDavid du Colombier Hole *table; 613e12c5d1SDavid du Colombier }; 623e12c5d1SDavid du Colombier 633e12c5d1SDavid du Colombier struct Bucket 643e12c5d1SDavid du Colombier { 653e12c5d1SDavid du Colombier int size; 663e12c5d1SDavid du Colombier int magic; 673e12c5d1SDavid du Colombier Bucket *next; 68*219b2ee8SDavid du Colombier ulong pc; 693e12c5d1SDavid du Colombier char data[1]; 703e12c5d1SDavid du Colombier }; 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier struct Arena 733e12c5d1SDavid du Colombier { 743e12c5d1SDavid du Colombier Lock; 753e12c5d1SDavid du Colombier Bucket *btab[Maxpow]; 763e12c5d1SDavid du Colombier int nbuck[Maxpow]; 77*219b2ee8SDavid du Colombier struct{ 78*219b2ee8SDavid du Colombier ulong pc; 79*219b2ee8SDavid du Colombier ulong alloc; 80*219b2ee8SDavid du Colombier ulong free; 81*219b2ee8SDavid du Colombier } trace[NTRACE]; 823e12c5d1SDavid du Colombier QLock rq; 833e12c5d1SDavid du Colombier Rendez r; 843e12c5d1SDavid du Colombier }; 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier static Arena arena; 873e12c5d1SDavid du Colombier static Xalloc xlists; 883e12c5d1SDavid du Colombier 893e12c5d1SDavid du Colombier void 903e12c5d1SDavid du Colombier xinit(void) 913e12c5d1SDavid du Colombier { 923e12c5d1SDavid du Colombier Hole *h, *eh; 933e12c5d1SDavid du Colombier int up, np0, np1; 943e12c5d1SDavid du Colombier 953e12c5d1SDavid du Colombier eh = &xlists.hole[Nhole-1]; 963e12c5d1SDavid du Colombier for(h = xlists.hole; h < eh; h++) 973e12c5d1SDavid du Colombier h->link = h+1; 983e12c5d1SDavid du Colombier 993e12c5d1SDavid du Colombier xlists.flist = xlists.hole; 1003e12c5d1SDavid du Colombier 1013e12c5d1SDavid du Colombier up = conf.upages; 1023e12c5d1SDavid du Colombier np1 = up; 1033e12c5d1SDavid du Colombier if(np1 > conf.npage1) 1043e12c5d1SDavid du Colombier np1 = conf.npage1; 1053e12c5d1SDavid du Colombier 106*219b2ee8SDavid du Colombier palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG; 1073e12c5d1SDavid du Colombier conf.npage1 -= np1; 1083e12c5d1SDavid du Colombier xhole(conf.base1, conf.npage1*BY2PG); 1093e12c5d1SDavid du Colombier conf.npage1 = conf.base1+(conf.npage1*BY2PG); 1103e12c5d1SDavid du Colombier up -= np1; 1113e12c5d1SDavid du Colombier 1123e12c5d1SDavid du Colombier np0 = up; 1133e12c5d1SDavid du Colombier if(np0 > conf.npage0) 1143e12c5d1SDavid du Colombier np0 = conf.npage0; 1153e12c5d1SDavid du Colombier 116*219b2ee8SDavid du Colombier palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG; 1173e12c5d1SDavid du Colombier conf.npage0 -= np0; 1183e12c5d1SDavid du Colombier xhole(conf.base0, conf.npage0*BY2PG); 1193e12c5d1SDavid du Colombier conf.npage0 = conf.base0+(conf.npage0*BY2PG); 1203e12c5d1SDavid du Colombier 1213e12c5d1SDavid du Colombier palloc.np0 = np0; 1223e12c5d1SDavid du Colombier palloc.np1 = np1; 1233e12c5d1SDavid du Colombier /* Save the bounds of kernel alloc memory for kernel mmu mapping */ 1243e12c5d1SDavid du Colombier conf.base0 = (ulong)KADDR(conf.base0); 1253e12c5d1SDavid du Colombier conf.base1 = (ulong)KADDR(conf.base1); 1263e12c5d1SDavid du Colombier conf.npage0 = (ulong)KADDR(conf.npage0); 1273e12c5d1SDavid du Colombier conf.npage1 = (ulong)KADDR(conf.npage1); 1283e12c5d1SDavid du Colombier } 1293e12c5d1SDavid du Colombier 1303e12c5d1SDavid du Colombier /* 1313e12c5d1SDavid du Colombier * NB. spanalloc memory will cause a panic if free'd 1323e12c5d1SDavid du Colombier */ 1333e12c5d1SDavid du Colombier void* 1343e12c5d1SDavid du Colombier xspanalloc(ulong size, int align, ulong span) 1353e12c5d1SDavid du Colombier { 1363e12c5d1SDavid du Colombier int i, j; 1373e12c5d1SDavid du Colombier ulong a, p, sinc; 1383e12c5d1SDavid du Colombier ulong ptr[Spanlist]; 1393e12c5d1SDavid du Colombier 1403e12c5d1SDavid du Colombier sinc = size/8; 1413e12c5d1SDavid du Colombier span = ~(span-1); 1423e12c5d1SDavid du Colombier for(i = 0; i < Spanlist; i++) { 1433e12c5d1SDavid du Colombier p = (ulong)xalloc(size+align); 1443e12c5d1SDavid du Colombier if(p == 0) 1453e12c5d1SDavid du Colombier break; 1463e12c5d1SDavid du Colombier 1473e12c5d1SDavid du Colombier a = p+align; 1483e12c5d1SDavid du Colombier a &= ~(align-1); 1493e12c5d1SDavid du Colombier if((a&span) == ((a+size)&span)) { 1503e12c5d1SDavid du Colombier for(j = 0; j < i; j++) 1513e12c5d1SDavid du Colombier if(ptr[j]) 1523e12c5d1SDavid du Colombier xfree((void*)ptr[j]); 1533e12c5d1SDavid du Colombier 1543e12c5d1SDavid du Colombier return (void*)a; 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier xfree((void*)p); 1573e12c5d1SDavid du Colombier ptr[i] = (ulong)xalloc(sinc); 1583e12c5d1SDavid du Colombier } 1593e12c5d1SDavid du Colombier USED(sinc); 1603e12c5d1SDavid du Colombier xsummary(); 1613e12c5d1SDavid du Colombier panic("xspanalloc: %d %d %lux\n", size, align, span); 1623e12c5d1SDavid du Colombier return 0; 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier void* 1663e12c5d1SDavid du Colombier xalloc(ulong size) 1673e12c5d1SDavid du Colombier { 1683e12c5d1SDavid du Colombier Xhdr *p; 1693e12c5d1SDavid du Colombier Hole *h, **l; 1703e12c5d1SDavid du Colombier 1713e12c5d1SDavid du Colombier size += BY2WD + sizeof(Xhdr); 1723e12c5d1SDavid du Colombier size &= ~(BY2WD-1); 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier lock(&xlists); 1753e12c5d1SDavid du Colombier l = &xlists.table; 1763e12c5d1SDavid du Colombier for(h = *l; h; h = h->link) { 1773e12c5d1SDavid du Colombier if(h->size >= size) { 1783e12c5d1SDavid du Colombier p = (Xhdr*)h->addr; 1793e12c5d1SDavid du Colombier h->addr += size; 1803e12c5d1SDavid du Colombier h->size -= size; 1813e12c5d1SDavid du Colombier if(h->size == 0) { 1823e12c5d1SDavid du Colombier *l = h->link; 1833e12c5d1SDavid du Colombier h->link = xlists.flist; 1843e12c5d1SDavid du Colombier xlists.flist = h; 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier unlock(&xlists); 1873e12c5d1SDavid du Colombier p = KADDR(p); 1883e12c5d1SDavid du Colombier memset(p, 0, size); 1893e12c5d1SDavid du Colombier p->magix = Magichole; 1903e12c5d1SDavid du Colombier p->size = size; 1913e12c5d1SDavid du Colombier return p->data; 1923e12c5d1SDavid du Colombier } 1933e12c5d1SDavid du Colombier l = &h->link; 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier unlock(&xlists); 1963e12c5d1SDavid du Colombier return nil; 1973e12c5d1SDavid du Colombier } 1983e12c5d1SDavid du Colombier 1993e12c5d1SDavid du Colombier void 2003e12c5d1SDavid du Colombier xfree(void *p) 2013e12c5d1SDavid du Colombier { 2023e12c5d1SDavid du Colombier Xhdr *x; 2033e12c5d1SDavid du Colombier 2043e12c5d1SDavid du Colombier x = (Xhdr*)((ulong)p - datoff); 2053e12c5d1SDavid du Colombier if(x->magix != Magichole) 2063e12c5d1SDavid du Colombier panic("xfree"); 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier xhole(PADDR(x), x->size); 2093e12c5d1SDavid du Colombier } 2103e12c5d1SDavid du Colombier 2113e12c5d1SDavid du Colombier void 2123e12c5d1SDavid du Colombier xhole(ulong addr, ulong size) 2133e12c5d1SDavid du Colombier { 2143e12c5d1SDavid du Colombier ulong top; 2153e12c5d1SDavid du Colombier Hole *h, *c, **l; 2163e12c5d1SDavid du Colombier 2173e12c5d1SDavid du Colombier if(size == 0) 2183e12c5d1SDavid du Colombier return; 2193e12c5d1SDavid du Colombier 2203e12c5d1SDavid du Colombier top = addr + size; 2213e12c5d1SDavid du Colombier lock(&xlists); 2223e12c5d1SDavid du Colombier l = &xlists.table; 2233e12c5d1SDavid du Colombier for(h = *l; h; h = h->link) { 2243e12c5d1SDavid du Colombier if(h->top == addr) { 2253e12c5d1SDavid du Colombier h->size += size; 2263e12c5d1SDavid du Colombier h->top = h->addr+h->size; 2273e12c5d1SDavid du Colombier c = h->link; 2283e12c5d1SDavid du Colombier if(c && h->top == c->addr) { 2293e12c5d1SDavid du Colombier h->top += c->size; 2303e12c5d1SDavid du Colombier h->size += c->size; 2313e12c5d1SDavid du Colombier h->link = c->link; 2323e12c5d1SDavid du Colombier c->link = xlists.flist; 2333e12c5d1SDavid du Colombier xlists.flist = c; 2343e12c5d1SDavid du Colombier } 2353e12c5d1SDavid du Colombier unlock(&xlists); 2363e12c5d1SDavid du Colombier return; 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier if(h->addr > addr) 2393e12c5d1SDavid du Colombier break; 2403e12c5d1SDavid du Colombier l = &h->link; 2413e12c5d1SDavid du Colombier } 2423e12c5d1SDavid du Colombier if(h && top == h->addr) { 2433e12c5d1SDavid du Colombier h->addr -= size; 2443e12c5d1SDavid du Colombier h->size += size; 2453e12c5d1SDavid du Colombier unlock(&xlists); 2463e12c5d1SDavid du Colombier return; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier 2493e12c5d1SDavid du Colombier if(xlists.flist == nil) { 2503e12c5d1SDavid du Colombier unlock(&xlists); 2513e12c5d1SDavid du Colombier print("xfree: no free holes, leaked %d bytes\n", size); 2523e12c5d1SDavid du Colombier return; 2533e12c5d1SDavid du Colombier } 2543e12c5d1SDavid du Colombier 2553e12c5d1SDavid du Colombier h = xlists.flist; 2563e12c5d1SDavid du Colombier xlists.flist = h->link; 2573e12c5d1SDavid du Colombier h->addr = addr; 2583e12c5d1SDavid du Colombier h->top = top; 2593e12c5d1SDavid du Colombier h->size = size; 2603e12c5d1SDavid du Colombier h->link = *l; 2613e12c5d1SDavid du Colombier *l = h; 2623e12c5d1SDavid du Colombier unlock(&xlists); 2633e12c5d1SDavid du Colombier } 2643e12c5d1SDavid du Colombier 265*219b2ee8SDavid du Colombier void 266*219b2ee8SDavid du Colombier alloctrace(void *p, ulong pc) 267*219b2ee8SDavid du Colombier { 268*219b2ee8SDavid du Colombier Bucket *bp; 269*219b2ee8SDavid du Colombier int i; 270*219b2ee8SDavid du Colombier 271*219b2ee8SDavid du Colombier bp = (Bucket*)((ulong)p - bdatoff); 272*219b2ee8SDavid du Colombier if(bp->size != 13) 273*219b2ee8SDavid du Colombier return; 274*219b2ee8SDavid du Colombier bp->pc = pc; 275*219b2ee8SDavid du Colombier lock(&arena); 276*219b2ee8SDavid du Colombier for(i = 0; i < NTRACE; i++){ 277*219b2ee8SDavid du Colombier if(arena.trace[i].pc == 0) 278*219b2ee8SDavid du Colombier arena.trace[i].pc = pc; 279*219b2ee8SDavid du Colombier if(arena.trace[i].pc == pc){ 280*219b2ee8SDavid du Colombier arena.trace[i].alloc++; 281*219b2ee8SDavid du Colombier break; 282*219b2ee8SDavid du Colombier } 283*219b2ee8SDavid du Colombier } 284*219b2ee8SDavid du Colombier unlock(&arena); 285*219b2ee8SDavid du Colombier } 286*219b2ee8SDavid du Colombier 2873e12c5d1SDavid du Colombier void* 2883e12c5d1SDavid du Colombier malloc(ulong size) 2893e12c5d1SDavid du Colombier { 2903e12c5d1SDavid du Colombier ulong next; 2913e12c5d1SDavid du Colombier int pow, n; 2923e12c5d1SDavid du Colombier Bucket *bp, *nbp; 2933e12c5d1SDavid du Colombier 294*219b2ee8SDavid du Colombier for(pow = 3; pow < Maxpow; pow++) 2953e12c5d1SDavid du Colombier if(size <= (1<<pow)) 2963e12c5d1SDavid du Colombier goto good; 2973e12c5d1SDavid du Colombier 2983e12c5d1SDavid du Colombier return nil; 2993e12c5d1SDavid du Colombier good: 3003e12c5d1SDavid du Colombier /* Allocate off this list */ 3013e12c5d1SDavid du Colombier lock(&arena); 3023e12c5d1SDavid du Colombier bp = arena.btab[pow]; 3033e12c5d1SDavid du Colombier if(bp) { 3043e12c5d1SDavid du Colombier arena.btab[pow] = bp->next; 305*219b2ee8SDavid du Colombier if(bp->magic != 0 || bp->size != pow){ 306*219b2ee8SDavid du Colombier unlock(&arena); 307*219b2ee8SDavid du Colombier panic("malloc bp %lux magic %lux size %d next %lux pow %d", bp, 308*219b2ee8SDavid du Colombier bp->magic, bp->size, bp->next, pow); 309*219b2ee8SDavid du Colombier } 310*219b2ee8SDavid du Colombier bp->magic = Magic2n; 3113e12c5d1SDavid du Colombier unlock(&arena); 3123e12c5d1SDavid du Colombier 3133e12c5d1SDavid du Colombier memset(bp->data, 0, size); 314*219b2ee8SDavid du Colombier bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); 3153e12c5d1SDavid du Colombier return bp->data; 3163e12c5d1SDavid du Colombier } 3173e12c5d1SDavid du Colombier unlock(&arena); 3183e12c5d1SDavid du Colombier 3193e12c5d1SDavid du Colombier size = sizeof(Bucket)+(1<<pow); 3203e12c5d1SDavid du Colombier size += 3; 3213e12c5d1SDavid du Colombier size &= ~3; 3223e12c5d1SDavid du Colombier 3233e12c5d1SDavid du Colombier if(pow < CUTOFF) { 3243e12c5d1SDavid du Colombier n = (CUTOFF-pow)+2; 3253e12c5d1SDavid du Colombier bp = xalloc(size*n); 3263e12c5d1SDavid du Colombier if(bp == nil) 3273e12c5d1SDavid du Colombier return nil; 3283e12c5d1SDavid du Colombier 329*219b2ee8SDavid du Colombier nbp = bp; 3303e12c5d1SDavid du Colombier lock(&arena); 3313e12c5d1SDavid du Colombier arena.nbuck[pow] += n; 332*219b2ee8SDavid du Colombier while(--n) { 3333e12c5d1SDavid du Colombier next = (ulong)nbp+size; 334*219b2ee8SDavid du Colombier nbp = (Bucket*)next; 3353e12c5d1SDavid du Colombier nbp->size = pow; 336*219b2ee8SDavid du Colombier nbp->next = arena.btab[pow]; 337*219b2ee8SDavid du Colombier arena.btab[pow] = nbp; 3383e12c5d1SDavid du Colombier } 3393e12c5d1SDavid du Colombier unlock(&arena); 3403e12c5d1SDavid du Colombier } 3413e12c5d1SDavid du Colombier else { 3423e12c5d1SDavid du Colombier bp = xalloc(size); 3433e12c5d1SDavid du Colombier if(bp == nil) 3443e12c5d1SDavid du Colombier return nil; 3453e12c5d1SDavid du Colombier 3463e12c5d1SDavid du Colombier arena.nbuck[pow]++; 3473e12c5d1SDavid du Colombier } 3483e12c5d1SDavid du Colombier 3493e12c5d1SDavid du Colombier bp->size = pow; 3503e12c5d1SDavid du Colombier bp->magic = Magic2n; 351*219b2ee8SDavid du Colombier bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); 3523e12c5d1SDavid du Colombier return bp->data; 3533e12c5d1SDavid du Colombier } 3543e12c5d1SDavid du Colombier 3553e12c5d1SDavid du Colombier void* 3563e12c5d1SDavid du Colombier smalloc(ulong size) 3573e12c5d1SDavid du Colombier { 3583e12c5d1SDavid du Colombier char *s; 3593e12c5d1SDavid du Colombier void *p; 3603e12c5d1SDavid du Colombier int attempt; 361*219b2ee8SDavid du Colombier Bucket *bp; 3623e12c5d1SDavid du Colombier 3633e12c5d1SDavid du Colombier for(attempt = 0; attempt < 1000; attempt++) { 3643e12c5d1SDavid du Colombier p = malloc(size); 365*219b2ee8SDavid du Colombier if(p != nil) { 366*219b2ee8SDavid du Colombier bp = (Bucket*)((ulong)p - bdatoff); 367*219b2ee8SDavid du Colombier bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); 3683e12c5d1SDavid du Colombier return p; 369*219b2ee8SDavid du Colombier } 3703e12c5d1SDavid du Colombier s = u->p->psstate; 3713e12c5d1SDavid du Colombier u->p->psstate = "Malloc"; 3723e12c5d1SDavid du Colombier qlock(&arena.rq); 3733e12c5d1SDavid du Colombier while(waserror()) 3743e12c5d1SDavid du Colombier ; 3753e12c5d1SDavid du Colombier sleep(&arena.r, return0, nil); 3763e12c5d1SDavid du Colombier poperror(); 3773e12c5d1SDavid du Colombier qunlock(&arena.rq); 3783e12c5d1SDavid du Colombier u->p->psstate = s; 3793e12c5d1SDavid du Colombier } 380*219b2ee8SDavid du Colombier print("%s:%d: out of memory in smalloc %d\n", u->p->text, u->p->pid, size); 381*219b2ee8SDavid du Colombier u->p->state = Broken; 382*219b2ee8SDavid du Colombier u->p->psstate = "NoMem"; 383*219b2ee8SDavid du Colombier for(;;) 384*219b2ee8SDavid du Colombier sched(); 3853e12c5d1SDavid du Colombier return 0; 3863e12c5d1SDavid du Colombier } 3873e12c5d1SDavid du Colombier 3883e12c5d1SDavid du Colombier int 3893e12c5d1SDavid du Colombier msize(void *ptr) 3903e12c5d1SDavid du Colombier { 3913e12c5d1SDavid du Colombier Bucket *bp; 3923e12c5d1SDavid du Colombier 3933e12c5d1SDavid du Colombier bp = (Bucket*)((ulong)ptr - bdatoff); 3943e12c5d1SDavid du Colombier if(bp->magic != Magic2n) 3953e12c5d1SDavid du Colombier panic("msize"); 3963e12c5d1SDavid du Colombier return 1<<bp->size; 3973e12c5d1SDavid du Colombier } 3983e12c5d1SDavid du Colombier 3993e12c5d1SDavid du Colombier void 4003e12c5d1SDavid du Colombier free(void *ptr) 4013e12c5d1SDavid du Colombier { 402*219b2ee8SDavid du Colombier ulong pc, n; 4033e12c5d1SDavid du Colombier Bucket *bp, **l; 4043e12c5d1SDavid du Colombier 4053e12c5d1SDavid du Colombier bp = (Bucket*)((ulong)ptr - bdatoff); 406*219b2ee8SDavid du Colombier l = &arena.btab[bp->size]; 407*219b2ee8SDavid du Colombier 408*219b2ee8SDavid du Colombier lock(&arena); 4093e12c5d1SDavid du Colombier if(bp->magic != Magic2n) 4103e12c5d1SDavid du Colombier panic("free"); 4113e12c5d1SDavid du Colombier bp->magic = 0; 4123e12c5d1SDavid du Colombier bp->next = *l; 4133e12c5d1SDavid du Colombier *l = bp; 414*219b2ee8SDavid du Colombier if(bp->size == 13) { 415*219b2ee8SDavid du Colombier pc = bp->pc; 416*219b2ee8SDavid du Colombier for(n = 0; n < NTRACE; n++){ 417*219b2ee8SDavid du Colombier if(arena.trace[n].pc == pc){ 418*219b2ee8SDavid du Colombier arena.trace[n].free++; 419*219b2ee8SDavid du Colombier break; 420*219b2ee8SDavid du Colombier } 421*219b2ee8SDavid du Colombier } 422*219b2ee8SDavid du Colombier } 4233e12c5d1SDavid du Colombier unlock(&arena); 4243e12c5d1SDavid du Colombier if(arena.r.p) 4253e12c5d1SDavid du Colombier wakeup(&arena.r); 4263e12c5d1SDavid du Colombier } 4273e12c5d1SDavid du Colombier 4283e12c5d1SDavid du Colombier void 4293e12c5d1SDavid du Colombier xsummary(void) 4303e12c5d1SDavid du Colombier { 4313e12c5d1SDavid du Colombier Hole *h; 4323e12c5d1SDavid du Colombier Bucket *k; 4333e12c5d1SDavid du Colombier int i, nfree, nused; 4343e12c5d1SDavid du Colombier 4353e12c5d1SDavid du Colombier i = 0; 4363e12c5d1SDavid du Colombier for(h = xlists.flist; h; h = h->link) 4373e12c5d1SDavid du Colombier i++; 4383e12c5d1SDavid du Colombier 4393e12c5d1SDavid du Colombier print("%d holes free\n", i); 4403e12c5d1SDavid du Colombier i = 0; 4413e12c5d1SDavid du Colombier for(h = xlists.table; h; h = h->link) { 4423e12c5d1SDavid du Colombier print("%.8lux %.8lux %d\n", h->addr, h->top, h->size); 4433e12c5d1SDavid du Colombier i += h->size; 4443e12c5d1SDavid du Colombier } 4453e12c5d1SDavid du Colombier print("%d bytes free\n", i); 4463e12c5d1SDavid du Colombier nused = 0; 4473e12c5d1SDavid du Colombier for(i = 3; i < Maxpow; i++) { 4483e12c5d1SDavid du Colombier if(arena.btab[i] == 0 && arena.nbuck[i] == 0) 4493e12c5d1SDavid du Colombier continue; 4503e12c5d1SDavid du Colombier nused += arena.nbuck[i]*(1<<i); 4513e12c5d1SDavid du Colombier nfree = 0; 4523e12c5d1SDavid du Colombier for(k = arena.btab[i]; k; k = k->next) 4533e12c5d1SDavid du Colombier nfree++; 4543e12c5d1SDavid du Colombier print("%8d %4d %4d\n", 1<<i, arena.nbuck[i], nfree); 4553e12c5d1SDavid du Colombier } 456*219b2ee8SDavid du Colombier for(i = 0; i < NTRACE && arena.trace[i].pc; i++) 457*219b2ee8SDavid du Colombier print("%lux %d %d\n", arena.trace[i].pc, arena.trace[i].alloc, arena.trace[i].free); 4583e12c5d1SDavid du Colombier print("%d bytes in pool\n", nused); 4593e12c5d1SDavid du Colombier } 460