## diffname port/alloc.c 1992/0618 ## diff -e /dev/null /n/bootesdump/1992/0618/sys/src/9/port/alloc.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #define nil ((void*)0) #define datoff ((int)&((Xhdr*)0)->data) enum { Nhole = 128, Magic = 0xDeadBabe, }; typedef struct Hole Hole; typedef struct Xalloc Xalloc; typedef struct Xhdr Xhdr; struct Hole { ulong addr; ulong size; ulong top; Hole *link; }; struct Xhdr { ulong size; ulong magix; char data[1]; }; struct Xalloc { Lock; Hole hole[Nhole]; Hole *flist; Hole *table; }; Xalloc xlists; void xinit(void) { Hole *h, *eh; eh = &xlists.hole[Nhole-1]; for(h = xlists.hole; h < eh; h++) h->link = h+1; xlists.flist = h; } void xhole(ulong addr, ulong size) { Hole *h, **l; lock(&xlists); l = &xlists.table; for(h = *l; h; h = h->link) { if(h->top == addr) { h->size += size; h->top = h->addr+h->size; unlock(&xlists); return; } if(h->addr > addr) break; l = &h->link; } if(xlists.flist == nil) { print("xfree: no free holes, leaked %d bytes\n", size); unlock(&xlists); return; } h = xlists.flist; xlists.flist = h->link; h->addr = addr; h->top = addr+size; h->size = size; h->link = *l; *l = h; unlock(&xlists); } void* xalloc(ulong size) { Hole *h, **l; Xhdr *p; size += sizeof(Xhdr); lock(&xlists); l = &xlists.table; for(h = *l; h; h = h->link) { if(h->size >= size) { p = (Xhdr*)h->addr; h->addr += size; h->size -= size; if(h->size == 0) { *l = h->link; h->link = xlists.flist; xlists.flist = h; } p->magix = Magic; p->size = size; unlock(&xlists); return p->data; } l = &h->link; } unlock(&xlists); return nil; } void xfree(void *p) { Xhdr *x; x = (Xhdr*)((ulong)p - datoff); if(x->magix != Magic) panic("xfree"); xhole((ulong)x, x->size); } void xsummary(void) { int i; Hole *h; i = 0; for(h = xlists.flist; h; h = h->link) i++; print("%d holes free\n", i); i = 0; for(h = xlists.table; h; h = h->link) { print("%lux %lux %d\n", h->addr, h->top, h->size); i += h->size; } print("%d bytes free\n", i); } . ## diffname port/alloc.c 1992/0619 ## diff -e /n/bootesdump/1992/0618/sys/src/9/port/alloc.c /n/bootesdump/1992/0619/sys/src/9/port/alloc.c 149a } void* malloc(ulong size) { int pow; Bucket *bp; for(pow = 1; pow < Maxpow; pow++) if(size <= (1<next; unlock(&arena); if(bp->magic != 0) panic("malloc"); bp->magic = Magic2n; memset(bp->data, 0, size); return bp->data; } unlock(&arena); size = sizeof(Bucket)+(1<size = pow; bp->magic = Magic2n; return bp->data; } void* smalloc(ulong size) { void *p; p = malloc(size); if(p == nil) panic("smalloc should sleep"); return p; } void free(void *ptr) { Bucket *bp, **l; bp = (Bucket*)((ulong)ptr - bdatoff); if(bp->magic != Magic2n) panic("free"); bp->magic = 0; lock(&arena); l = &arena.btab[bp->size]; bp->next = *l; *l = bp; unlock(&arena); . 146c print("%.8lux %.8lux %d\n", h->addr, h->top, h->size); . 133a xhole(ulong addr, ulong size) { ulong top; Hole *h, *c, **l; if(size == 0) return; top = addr + size; lock(&xlists); l = &xlists.table; for(h = *l; h; h = h->link) { if(h->top == addr) { h->size += size; h->top = h->addr+h->size; c = h->link; if(c && h->top == c->addr) { h->top += c->size; h->size += c->size; h->link = c->link; c->link = xlists.flist; xlists.flist = c; } unlock(&xlists); return; } if(h->addr > addr) break; l = &h->link; } if(h && top == h->addr) { h->addr -= size; h->size += size; unlock(&xlists); return; } if(xlists.flist == nil) { unlock(&xlists); print("xfree: no free holes, leaked %d bytes\n", size); return; } h = xlists.flist; xlists.flist = h->link; h->addr = addr; h->top = top; h->size = size; h->link = *l; *l = h; unlock(&xlists); } void . 130c xhole(PADDR(x), x->size); . 127c if(x->magix != Magichole) . 110c p = KADDR(p); memset(p, 0, size); p->magix = Magichole; . 96c size += BY2WD + sizeof(Xhdr); size &= ~(BY2WD-1); . 94a Hole *h, **l; . 93d 80,87c np0 = up; if(np0 > conf.npage0) np0 = conf.npage0; palloc.p0 = conf.base0; conf.base0 += np0*BY2PG; conf.npage0 -= np0; xhole(conf.base0, conf.npage0*BY2PG); palloc.np0 = np0; palloc.np1 = np1; . 74,78c palloc.p1 = conf.base1; conf.base1 += np1*BY2PG; conf.npage1 -= np1; xhole(conf.base1, conf.npage1*BY2PG); up -= np1; . 60,72c up = conf.upages; np1 = up; if(np1 > conf.npage1) np1 = conf.npage1; . 55,58c ktop = PGROUND((ulong)end); ktop = PADDR(ktop); conf.npage0 -= ktop/BY2PG; conf.base0 += ktop; . 52,53c xlists.flist = xlists.hole; . 46a int up, np0, np1; . 45a ulong ktop; . 42a struct Arena { Lock; Bucket *btab[Maxpow]; }; static Arena arena; static Xalloc xlists; void* ialloc(ulong size, int align) { ulong p; if(align) { size += BY2PG; p = (ulong)xalloc(size); p += BY2PG; p &= ~(BY2PG-1); return (void*)p; } return xalloc(size); } void* iallocspan(ulong size, int quanta, ulong span) { return ialloc(size, quanta); } . 41c struct Bucket { int size; int magic; Bucket *next; char data[1]; }; . 17a typedef struct Bucket Bucket; typedef struct Arena Arena; . 11,12c Maxpow = 16, Nhole = 128, Magichole = 0xDeadBabe, Magic2n = 0xBadC0c0a, . 8a #define nil ((void*)0) #define datoff ((ulong)&((Xhdr*)0)->data) #define bdatoff ((ulong)&((Bucket*)0)->data) . 6,7d ## diffname port/alloc.c 1992/0620 ## diff -e /n/bootesdump/1992/0619/sys/src/9/port/alloc.c /n/bootesdump/1992/0620/sys/src/9/port/alloc.c 311a } void xsummary(void) { Hole *h; Bucket *k; int i, nfree; i = 0; for(h = xlists.flist; h; h = h->link) i++; print("%d holes free\n", i); i = 0; for(h = xlists.table; h; h = h->link) { print("%.8lux %.8lux %d\n", h->addr, h->top, h->size); i += h->size; } print("%d bytes free\n", i); for(i = 3; i < Maxpow; i++) { if(arena.btab[i] == 0 && arena.nbuck[i] == 0) continue; nfree = 0; for(k = arena.btab[i]; k; k = k->next) nfree++; print("%8d %4d %4d\n", 1<data) #define bdatoff ((ulong)((Bucket*)0)->data) . 6a /* * Plan 9 has two kernel allocators, the x... routines provide a first * fit hole allocator which should be used for permanent or large structures. * Routines are provided to allocate aligned memory which does not cross * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is * a 2n bucket allocator which steals from the x routines. This should * be used for small frequently used structures. */ . ## diffname port/alloc.c 1992/0622 ## diff -e /n/bootesdump/1992/0621/sys/src/9/port/alloc.c /n/bootesdump/1992/0622/sys/src/9/port/alloc.c 309a } . 308c if(p == nil) { print("asking for %d\n", size); xsummary(); . 76,90d ## diffname port/alloc.c 1992/0623 ## diff -e /n/bootesdump/1992/0622/sys/src/9/port/alloc.c /n/bootesdump/1992/0623/sys/src/9/port/alloc.c 298a } int msize(void *ptr) { Bucket *bp; bp = (Bucket*)((ulong)ptr - bdatoff); if(bp->magic != Magic2n) panic("msize"); return 1<size; . 173d 168a unlock(&xlists); . ## diffname port/alloc.c 1992/0625 ## diff -e /n/bootesdump/1992/0623/sys/src/9/port/alloc.c /n/bootesdump/1992/0625/sys/src/9/port/alloc.c 326a if(arena.r.p) wakeup(&arena.r); . 292,296c for(;;) { p = malloc(size); if(p != nil) return p; s = u->p->psstate; u->p->psstate = "Malloc"; qlock(&arena.rq); while(waserror()) ; sleep(&arena.r, return0, nil); poperror(); qunlock(&arena.rq); u->p->psstate = s; . 289a char *s; . 115a /* Save the bounds of kernel alloc memory for kernel mmu mapping (NeXT) */ conf.base0 = (ulong)KADDR(conf.base0); conf.base1 = (ulong)KADDR(conf.base1); conf.npage0 = (ulong)KADDR(conf.npage0); conf.npage1 = (ulong)KADDR(conf.npage1); . 112a conf.npage0 = conf.base0+(conf.npage0*BY2PG); . 102a conf.npage1 = conf.base1+(conf.npage1*BY2PG); . 70a QLock rq; Rendez r; . ## diffname port/alloc.c 1992/0707 ## diff -e /n/bootesdump/1992/0625/sys/src/9/port/alloc.c /n/bootesdump/1992/0707/sys/src/9/port/alloc.c 316c pexit(Enomem, 1); return 0; . 302c for(attempt = 0; attempt < 1000; attempt++) { . 300a int attempt; . 263c for(pow = 3; pow <= Maxpow; pow++) . 22c Maxpow = 18, . 5a #include "error.h" . ## diffname port/alloc.c 1992/0708 ## diff -e /n/bootesdump/1992/0707/sys/src/9/port/alloc.c /n/bootesdump/1992/0708/sys/src/9/port/alloc.c 153a USED(sinc); . 152c xfree((void*)p); ptr[i] = (ulong)xalloc(sinc); . 148c if(ptr[j]) xfree((void*)ptr[j]); . 142c panic("xspanalloc: size %d align %d span %lux", size, align, span); . 137a sinc = span/8; . 135c ulong a, p, sinc; . ## diffname port/alloc.c 1992/0715 ## diff -e /n/bootesdump/1992/0708/sys/src/9/port/alloc.c /n/bootesdump/1992/0715/sys/src/9/port/alloc.c 91,95d 82d ## diffname port/alloc.c 1992/0720 ## diff -e /n/bootesdump/1992/0715/sys/src/9/port/alloc.c /n/bootesdump/1992/0720/sys/src/9/port/alloc.c 286,288c size += 3; size &= ~3; if(pow < CUTOFF) { n = (CUTOFF-pow)+2; bp = xalloc(size*n); if(bp == nil) return nil; next = (ulong)bp+size; nbp = (Bucket*)next; lock(&arena); arena.btab[pow] = nbp; arena.nbuck[pow] += n; for(n -= 2; n; n--) { next = (ulong)nbp+size; nbp->next = (Bucket*)next; nbp->size = pow; nbp = nbp->next; } nbp->size = pow; unlock(&arena); } else { bp = xalloc(size); if(bp == nil) return nil; } . 284a . 283d 259,260c ulong next; int pow, n; Bucket *bp, *nbp; . 137c panic("xspanalloc: %d %d %lux", size, align, span); . 23a CUTOFF = 12, . ## diffname port/alloc.c 1992/0726 ## diff -e /n/bootesdump/1992/0720/sys/src/9/port/alloc.c /n/bootesdump/1992/0726/sys/src/9/port/alloc.c 116c /* Save the bounds of kernel alloc memory for kernel mmu mapping */ . ## diffname port/alloc.c 1992/0729 ## diff -e /n/bootesdump/1992/0726/sys/src/9/port/alloc.c /n/bootesdump/1992/0729/sys/src/9/port/alloc.c 153c xsummary(); panic("xspanalloc: %d %d %lux\n", size, align, span); . 138c break; . 133c sinc = size/8; . ## diffname port/alloc.c 1992/0912 ## diff -e /n/bootesdump/1992/0729/sys/src/9/port/alloc.c /n/bootesdump/1992/0912/sys/src/9/port/alloc.c 403a print("%d bytes in pool\n", nused); . 398a nused += arena.nbuck[i]*(1<size]; lock(&arena); . 280c panic("malloc %lux", bp->magic); . ## diffname port/alloc.c 1993/0120 ## diff -e /n/bootesdump/1993/0116/sys/src/9/port/alloc.c /n/bootesdump/1993/0120/sys/src/9/port/alloc.c 318a unlock(&arena); . 317a lock(&arena); . 310d 308c nbp->next = arena.btab[pow]; arena.btab[pow] = nbp; . 306c nbp = (Bucket*)next; . 304c while(--n) { . 302d 299,300c nbp = bp; . 266c for(pow = 3; pow < Maxpow; pow++) . ## diffname port/alloc.c 1993/0121 ## diff -e /n/bootesdump/1993/0120/sys/src/9/port/alloc.c /n/bootesdump/1993/0121/sys/src/9/port/alloc.c 284c memset(bp->data, 0, size); . 279,280c if(bp->magic != 0 || bp->size != pow) panic("malloc bp %lux magic %lux size %d next %lux pow %d", bp, bp->magic, bp->size, bp->next, pow); . ## diffname port/alloc.c 1993/0205 ## diff -e /n/bootesdump/1993/0121/sys/src/9/port/alloc.c /n/bootesdump/1993/0205/sys/src/9/port/alloc.c 319d 317d 283a unlock(&arena); . 282c } . 277,279c if(bp->magic != 0 || bp->size != pow){ unlock(&arena); . ## diffname port/alloc.c 1993/0501 ## diff -e /n/bootesdump/1993/0205/sys/src/9/port/alloc.c /n/fornaxdump/1993/0501/sys/src/brazil/port/alloc.c 372a lock(&arena); l = &arena.btab[bp->size]; . 371a . 367,369d 344c up->psstate = s; . 336,337c s = up->psstate; up->psstate = "Malloc"; . 309a nbp->size = pow; . 307,308c nbp = nbp->next; . 305c nbp->next = (Bucket*)next; . 303c for(n -= 2; n; n--) { . 301a arena.btab[pow] = nbp; . 300c next = (ulong)bp+size; nbp = (Bucket*)next; . 285c if(bp->magic != 0) panic("malloc"); bp->magic = Magic2n; memset(bp->data, 0, size); . 277,282d 266c for(pow = 3; pow <= Maxpow; pow++) . ## diffname port/alloc.c 1993/0515 ## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/0515/sys/src/brazil/port/alloc.c 109,110c palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG; . 98,99c palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG; . ## diffname port/alloc.c 1993/1121 ## diff -e /n/fornaxdump/1993/0515/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1121/sys/src/brazil/port/alloc.c 320a bp->pc = pc; . 281c bp->pc = pc; . 262a ulong pc; pc = getcallerpc(0); . 65a ulong pc; . ## diffname port/alloc.c 1993/1125 ## diff -e /n/fornaxdump/1993/1121/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1125/sys/src/brazil/port/alloc.c 338a } . 337c if(p != nil) { bp = (Bucket*)((ulong)p - bdatoff); bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); . 333a Bucket *bp; . 324c bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); . 284c bp->pc = getcallerpc(((uchar*)&size) - sizeof(size)); . 264,265d ## diffname port/alloc.c 1993/1231 ## diff -e /n/fornaxdump/1993/1125/sys/src/brazil/port/alloc.c /n/fornaxdump/1993/1231/sys/src/brazil/port/alloc.c 152,155c else v = a; if(align > 1) v = (v + align) & ~(align-1); return (void*)v; . 140,150c if(span > 2) { v = (a + span) & ~(span-1); t = v - a; if(t > 0) xhole(PADDR(a), t); t = a + span - v; if(t > 0) xhole(PADDR(v+size+align), t); . 133,138c a = (ulong)xalloc(size+align+span); if(a == 0) panic("xspanalloc: %d %d %lux\n", size, align, span); . 129,131c ulong a, v, t; . ## diffname port/alloc.c 1994/0208 ## diff -e /n/fornaxdump/1993/1231/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0208/sys/src/brazil/port/alloc.c 120a /* setup initial memory allocations for interrupt time */ qinit(); . ## diffname port/alloc.c 1994/0222 ## diff -e /n/fornaxdump/1994/0208/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0222/sys/src/brazil/port/alloc.c 371c panic("free %lux %lux", bp->magic, bp->pc); . 277c panic("malloc %lux %lux", bp->magic, bp->pc); . ## diffname port/alloc.c 1994/0223 ## diff -e /n/fornaxdump/1994/0222/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0223/sys/src/brazil/port/alloc.c 196,197c if(x->magix != Magichole) { uchar *a; int i; a = (uchar*)x; for(i = 0; i < 32; i++) print("#%lux ", *a++); panic("xfree(0x%lux) 0x%lux!=0x%lux", p, Magichole, x->magix); } . 189a void* xalloc(ulong size) { return xallocz(size, 1); } . 179c if(zero) memset(p, 0, size); . 157c xallocz(ulong size, int zero) . ## diffname port/alloc.c 1994/0224 ## diff -e /n/fornaxdump/1994/0223/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0224/sys/src/brazil/port/alloc.c 211d 204,208c xsummary(); . ## diffname port/alloc.c 1994/0306 ## diff -e /n/fornaxdump/1994/0224/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0306/sys/src/brazil/port/alloc.c 295,296c size += BY2V; size &= ~(BY2V-1); . 162,163c size += BY2V + sizeof(Xhdr); size &= ~(BY2V-1); . ## diffname port/alloc.c 1994/0322 ## diff -e /n/fornaxdump/1994/0306/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0322/sys/src/brazil/port/alloc.c 386c iunlock(&arena); . 382c ilock(&arena); . 346d 342,344c if(p != nil) . 338d 328c . 316c iunlock(&arena); . 306c ilock(&arena); . 292c iunlock(&arena); . 288,289c if(zero) memset(bp->data, 0, size); . 282c iunlock(&arena); . 278c ilock(&arena); . 265c mallocz(ulong size, int zero) . 261c iunlock(&xlists); . 249c iunlock(&xlists); . 244c iunlock(&xlists); . 234c iunlock(&xlists); . 220c ilock(&xlists); . 191,196d 187c iunlock(&xlists); . 177c iunlock(&xlists); . 165c ilock(&xlists); . 121,123d ## diffname port/alloc.c 1994/0812 ## diff -e /n/fornaxdump/1994/0322/sys/src/brazil/port/alloc.c /n/fornaxdump/1994/0812/sys/src/brazil/port/alloc.c 324a malloc(ulong size) { return mallocz(size, 1); } void* . ## diffname port/alloc.c 1995/0616 ## diff -e /n/fornaxdump/1994/0812/sys/src/brazil/port/alloc.c /n/fornaxdump/1995/0616/sys/src/brazil/port/alloc.c 105c np0 = upages; . 103c upages -= np1; . 94,95c upages = conf.upages; np1 = upages; . 86c int upages, np0, np1; . ## diffname port/alloc.c 1996/0217 ## diff -e /n/fornaxdump/1995/0616/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0217/sys/src/brazil/port/alloc.c 18d ## diffname port/alloc.c 1996/0305 ## diff -e /n/fornaxdump/1996/0217/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0305/sys/src/brazil/port/alloc.c 266a . ## diffname port/alloc.c 1996/0324 ## diff -e /n/fornaxdump/1996/0305/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/0324/sys/src/brazil/port/alloc.c 23c Maxpow = 19, . ## diffname port/alloc.c 1996/1120 ## diff -e /n/fornaxdump/1996/0324/sys/src/brazil/port/alloc.c /n/fornaxdump/1996/1120/sys/src/brazil/port/alloc.c 373c panic("free %lux %lux %lux", bp->magic, bp->pc, getcallerpc(ptr)); . 307d 301,305c l = &arena.btab[pow]; /* add all but the last to the free list */ while(--n){ bp->size = pow; bp->next = *l; *l = bp; bp = (Bucket*)((ulong)bp+size); . 299d 296,297d 259c Bucket *bp, **l; . 257d ## diffname port/alloc.c 1997/1101 ## diff -e /n/fornaxdump/1996/1120/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1101/sys/src/brazil/port/alloc.c 410c return compacted; . 399,408c } int poolcompact(Pool *pool) { Bhdr *base, *limit, *ptr, *end, *next; int compacted, recov, nb; if(pool->move == nil || pool->lastfree == pool->nfree) return 0; pool->lastfree = pool->nfree; base = pool->chain; ptr = B2NB(base); /* First Block in arena has clink */ limit = B2LIMIT(base); compacted = 0; pool->root = nil; end = ptr; recov = 0; while(base != nil) { next = B2NB(ptr); if(ptr->magic == MAGIC_A) { if(ptr != end) { memmove(end, ptr, ptr->size); pool->move(B2D(ptr), B2D(end)); recov = (uchar*)ptr - (uchar*)end; compacted = 1; } end = B2NB(end); } if(next >= limit) { nb = (uchar*)limit - (uchar*)end; //print("recovered %d bytes\n", recov); //print("%d bytes at end\n", nb); USED(recov); if(nb > 0){ if(nb < pool->quanta+1) panic("poolcompact: leftover too small\n"); end->size = nb; pooladd(pool, end); } base = base->clink; if(base == nil) break; ptr = B2NB(base); end = ptr; /* could do better by copying between chains */ limit = B2LIMIT(base); recov = 0; } else ptr = next; . 393,397c for(i=0; iname) == 0){ if(maxsize) p->maxsize = maxsize; if(quanta) p->quanta = quanta; if(chunk) p->chunk = chunk; return; } . 389,391c void poolsetparam(char *name, ulong maxsize, int quanta, int chunk) { Pool *p; int i; . 385,387c p->move = move; } . 383c poolsetcompact(Pool *p, void (*move)(void*, void*)) . 380a */ . 372,379c while(base != nil) { print("\tbase #%.8lux ptr #%.8lux", base, ptr); if(ptr->magic == MAGIC_A) print("\tA%.5d\n", ptr->size); else if(ptr->magic == MAGIC_E) print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize); else print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n", ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent); ptr = B2NB(ptr); if(ptr >= limit) { print("link to #%.8lux\n", base->clink); base = base->clink; if(base == nil) break; ptr = base; limit = B2LIMIT(base); } } return; . 368,370c b = p->chain; if(b == nil) return; base = b; ptr = b; limit = B2LIMIT(b); . 366c Bhdr *b, *base, *limit, *ptr; . 364c pooldump(Pool *p) . 362a /* . 357,360c for(i = 0; i < table.n; i++) print("Arena: %s cursize=%d; maxsize=%d\n", table.pool[i].name, table.pool[i].cursize, table.pool[i].maxsize); . 355c int i; . 352,353c void poolsummary(void) . 350a */ . 348,349d 334,346c if(b == nil) return; print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n", b, b->left, b->right, c, d, b->size, b->fwd, b->prev); d++; for(t = b->fwd; t != b; t = t->fwd) print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd); pooldump(b->left, d, 'l'); pooldump(b->right, d, 'r'); } void poolshow(void) { int i; for(i = 0; i < table.n; i++) { print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root); pooldump(table.pool[i].root, 0, 'R'); . 330,332c Bhdr *t; . 327,328c /* void pooldump(Bhdr *b, int d, int c) . 324c return malloc(n*szelem); . 322c calloc(ulong n, ulong szelem) . 318c D2B(b, v); return b->size - BHDRSIZE; . 315,316c int msize(void *v) { Bhdr *b; . 313a return nv; } . 312c osize = b->size - BHDRSIZE; if(osize >= size) return v; nv = poolalloc(mainmem, size); if(nv != nil) { memmove(nv, v, osize); free(v); . 295,310c D2B(b, v); . 289,293c if(v == nil) return malloc(size); . 285,287c void* realloc(void *v, ulong size) { Bhdr *b; void *nv; int osize; . 283c } . 279,281c void free(void *v) { Bhdr *b; if(v != nil) { D2B(b, v); poolfree(mainmem, v); . 277c v = poolalloc(mainmem, size); if(clr && v != nil) memset(v, 0, size); return v; } . 274,275c void* mallocz(ulong size, int clr) { void *v; . 267,272c for(;;) { v = poolalloc(mainmem, size); if(v != nil) break; tsleep(&up->sleep, return0, 0, 100); } memset(v, 0, size); return v; } . 264,265c void* smalloc(ulong size) { void *v; . 260,262c v = poolalloc(mainmem, size); if(v != nil) memset(v, 0, size); return v; } . 257,258c void *v; . 255c malloc(ulong size) . 243,251c return n; . 238,241d 227,236d 224,225c else n = 0; . 209,222c if(signed_off > 0) { signed_off -= n; if(signed_off < 0) { memmove(va, va+n+signed_off, -signed_off); n = -signed_off; . 206,207c n = 0; signed_off = offset; for(i = 0; i < table.n; i++) { p = &table.pool[i]; n += snprint(va+n, count-n, "%11d %11d %11d %11d %11d %11d %s\n", p->cursize, p->maxsize, p->hw, p->nalloc, p->nfree, p->nbrk, p->name); . 203,204c Pool *p; int n, i, signed_off; . 200,201c int poolread(char *va, int count, ulong offset) . 197c c = B2PT(b)->hdr; if(c->magic == MAGIC_F) { /* Join backward */ pooldel(p, c); b->magic = 0; c->size += b->size; b = c; B2T(b)->hdr = b; } pooladd(p, b); iunlock(&p->l); . 192,195c D2B(b, v); ilock(&p->l); p->nfree++; p->cursize -= b->size; c = B2NB(b); if(c->magic == MAGIC_F) { /* Join forward */ pooldel(p, c); c->magic = 0; b->size += c->size; B2T(b)->hdr = b; . 190c Bhdr *b, *c; . 188c poolfree(Pool *p, void *v) . 183,184c t->magic = MAGIC_E; /* Make a leader */ t->size = ldr; t->csize = ns+ldr; t->clink = p->chain; p->chain = t; B2T(t)->hdr = t; t = B2NB(t); t->magic = MAGIC_A; /* Make the block we are going to return */ t->size = size; B2T(t)->hdr = t; q = t; ns -= size; /* Free the rest */ if(ns > 0) { q = B2NB(t); q->size = ns; B2T(q)->hdr = q; pooladd(p, q); } B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */ p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(t); . 161,181c p->nbrk++; t = xalloc(alloc); if(t == nil) { iunlock(&p->l); return nil; . 158,159c iunlock(&p->l); print("arena too large: size %d cursize %d arenasize %d maxsize %d\n", size, p->cursize, p->arenasize, p->maxsize); return nil; } . 152,156c if(poolcompact(p)) { iunlock(&p->l); return poolalloc(p, size); } . 149,150c alloc = ns+ldr+sizeof(t->magic); p->arenasize += alloc; if(p->arenasize > p->maxsize) { p->arenasize -= alloc; . 146,147c ns = p->chunk; if(size > ns) ns = size; ldr = p->quanta+1; . 143,144c if(q != nil) { pooldel(p, q); q->magic = MAGIC_A; frag = q->size - size; if(frag < (size>>2)) { p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(q); } /* Split */ ns = q->size - size; q->size = size; B2T(q)->hdr = q; t = B2NB(q); t->size = ns; B2T(t)->hdr = t; pooladd(p, t); p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(q); } . 134,141c ilock(&p->l); p->nalloc++; t = p->root; q = nil; while(t) { if(t->size == size) { pooldel(p, t); t->magic = MAGIC_A; p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(t); } if(size < t->size) { q = t; t = t->left; } else t = t->right; . 130,132c size = (size + BHDRSIZE + p->quanta) & ~(p->quanta); . 128c Bhdr *q, *t; int alloc, ldr, ns, frag; . 126c poolalloc(Pool *p, int size) . 122,124d 108,119c q->parent = tp; if(size < tp->size) tp->left = q; else tp->right = q; . 104,106c tp = nil; while(t != nil) { if(size == t->size) { q->fwd = t->fwd; q->fwd->prev = q; q->prev = t; t->fwd = q; return; } tp = t; if(size < t->size) t = t->left; else t = t->right; } . 98,102c size = q->size; . 93,96c t = p->root; if(t == nil) { p->root = q; return; } . 91c q->left = nil; q->right = nil; q->parent = nil; q->fwd = q; q->prev = q; . 87,89c q->magic = MAGIC_F; . 84,85c int size; Bhdr *tp, *t; . 82c pooladd(Pool *p, Bhdr *q) . 80a if(t->left == nil) rp = t->right; else { if(t->right == nil) rp = t->left; else { f = t; rp = t->right; s = rp->left; while(s != nil) { f = rp; rp = s; s = rp->left; } if(f != t) { s = rp->right; f->left = s; if(s != nil) s->parent = f; s = t->right; rp->right = s; if(s != nil) s->parent = rp; } s = t->left; rp->left = s; s->parent = rp; } } q = t->parent; if(q == nil) p->root = rp; else { if(t == q->left) q->left = rp; else q->right = rp; } if(rp != nil) rp->parent = q; } . 78,79c if(t->parent == nil && p->root != t) { t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->fwd != t) { f = t->fwd; s = t->parent; f->parent = s; if(s == nil) p->root = f; else { if(s->left == t) s->left = f; else s->right = f; } rp = t->left; f->left = rp; if(rp != nil) rp->parent = f; rp = t->right; f->right = rp; if(rp != nil) rp->parent = f; t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } . 71,76c Bhdr *s, *f, *rp, *q; . 69c void pooldel(Pool *p, Bhdr *t) . 62,67c return p->chain; } . 60c Bhdr* poolchain(Pool *p) . 52,58c int poolcompact(Pool*); . 45,50c Pool* mainmem = &table.pool[0]; Pool* imagmem = &table.pool[1]; . 39,42c int n; Pool pool[MAXPOOL]; Lock l; } table = { 2, { { "Main", 4*1024*1024, 31, 128*1024 }, { "Image", 8*1024*1024, 31, 2*1024*1024 }, } . 31,37c struct . 23,28c char* name; ulong maxsize; int quanta; int chunk; ulong cursize; ulong arenasize; ulong hw; Lock l; Bhdr* root; Bhdr* chain; int nalloc; int nfree; int nbrk; int lastfree; void (*move)(void*, void*); . 9,21c struct Pool . 7a #define left u.s.bhl #define right u.s.bhr #define fwd u.s.bhf #define prev u.s.bhv #define parent u.s.bhp . 3a #include "pool.h" . ## diffname port/alloc.c 1997/1105 ## diff -e /n/emeliedump/1997/1101/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1105/sys/src/brazil/port/alloc.c 603a int recur(Bhdr *t) { if(t == 0) return 1; if(((ulong)t) < 0x80000000) return 0; if(((ulong)t) > 0x90000000) return 0; return recur(t->right) && recur(t->left); } int poolok(void) { return recur(mainmem->root); } . ## diffname port/alloc.c 1997/1108 ## diff -e /n/emeliedump/1997/1105/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1108/sys/src/brazil/port/alloc.c 43c { "Image", 16*1024*1024, 31, 2*1024*1024 }, . ## diffname port/alloc.c 1997/1202 ## diff -e /n/emeliedump/1997/1108/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1202/sys/src/brazil/port/alloc.c 188a if(size < 0 || size >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; . ## diffname port/alloc.c 1997/1208 ## diff -e /n/emeliedump/1997/1202/sys/src/brazil/port/alloc.c /n/emeliedump/1997/1208/sys/src/brazil/port/alloc.c 622c if(x & 1) return recur(mainmem->root); return recur(imagmem->root); . 620c poolok(int x) . ## diffname port/alloc.c 1998/0128 ## diff -e /n/emeliedump/1997/1208/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0128/sys/src/brazil/port/alloc.c 257,258c print("%s arena too large: size %d cursize %d arenasize %d maxsize %d\n", p->name, size, p->cursize, p->arenasize, p->maxsize); . ## diffname port/alloc.c 1998/0221 ## diff -e /n/emeliedump/1998/0128/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0221/sys/src/brazil/port/alloc.c 618,625d ## diffname port/alloc.c 1998/0512 ## diff -e /n/emeliedump/1998/0221/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0512/sys/src/brazil/port/alloc.c 233c pooladd(p, t); . 99c if(t->right == nil) . 90c . 81c . 68c . ## diffname port/alloc.c 1998/0825 ## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0825/sys/src/brazil/port/alloc.c 487c print("Arena: %s cursize=%lud; maxsize=%lud\n", table.pool[i].name, table.pool[i].cursize, table.pool[i].maxsize); . 340c n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n", . 257c print("%s arena too large: size %d cursize %lud arenasize %lud maxsize %lud\n", . ## diffname port/alloc.c 1998/0916 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/port/alloc.c /n/emeliedump/1998/0916/sys/src/brazil/port/alloc.c 489a table.pool[i].arenasize, . 487c print("Arena: %s cursize=%lud; arenasize=%lud; maxsize=%lud\n", . ## diffname port/alloc.c 1999/0125 ## diff -e /n/emeliedump/1998/0916/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0125/sys/src/brazil/port/alloc.c 550a if(move != nil) p->move = move; . 549c if(chunk != 0) . 547c if(quanta != 0) . 545c if(maxsize != 0) . 533,538d 531c poolsetparam(char *name, ulong maxsize, int quanta, int chunk, void (*move)(void*, void*)) . ## diffname port/alloc.c 1999/0209 ## diff -e /n/emeliedump/1999/0125/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0209/sys/src/brazil/port/alloc.c 184c poolalloc(Pool *p, long size) . ## diffname port/alloc.c 1999/0211 ## diff -e /n/emeliedump/1999/0209/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0211/sys/src/brazil/port/alloc.c 257c print("%s arena too large: size %ld cursize %lud arenasize %lud maxsize %lud\n", . ## diffname port/alloc.c 1999/0501 ## diff -e /n/emeliedump/1999/0211/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0501/sys/src/brazil/port/alloc.c 431a { Bhdr *h; D2B(h, nv); B2T(h)->pad = getcallerpc(&size); } . 396a { Bhdr *h; D2B(h, v); B2T(h)->pad = getcallerpc(&size); } . 385a { Bhdr *h; D2B(h, v); B2T(h)->pad = getcallerpc(&size); } . 370a { Bhdr *h; D2B(h, v); B2T(h)->pad = getcallerpc(&size); } . ## diffname port/alloc.c 1999/0511 ## diff -e /n/emeliedump/1999/0501/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0511/sys/src/brazil/port/alloc.c 410a memset(v, 0, size); . 406d ## diffname port/alloc.c 1999/0526 ## diff -e /n/emeliedump/1999/0511/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0526/sys/src/brazil/port/alloc.c 410d 406c memset(v, 0, size); if(v != nil){ . 371c if(v != nil){ . ## diffname port/alloc.c 1999/0527 ## diff -e /n/emeliedump/1999/0526/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0527/sys/src/brazil/port/alloc.c 636a } enum { Hdrspc = 64, /* leave room for high-level headers */ Bdead = 0x51494F42, /* "QIOB" */ }; struct { Lock; ulong bytes; } ialloc; /* * allocate blocks, round the data base upt to a multiple of BLOCKALIGN. */ Block* allocb(int size) { Block *b; ulong addr; int n; n = sizeof(Block) + size; b = poolalloc(mainmem, n+Hdrspc); if(b == 0) exhausted("Blocks"); memset(b, 0, sizeof(Block)); /* align start of data portion by rounding up */ addr = (ulong)b; addr = ROUND(addr + sizeof(Block), BLOCKALIGN); b->base = (uchar*)addr; /* align end of data portion by rounding down */ b->lim = ((uchar*)b) + msize(b); addr = (ulong)(b->lim); addr = addr & ~(BLOCKALIGN-1); b->lim = (uchar*)addr; /* leave sluff at beginning for added headers */ b->rp = b->lim - ROUND(size, BLOCKALIGN); if(b->rp < b->base) panic("allocb"); b->wp = b->rp; tagwithpc(b, getcallerpc(&size)); return b; } /* * interrupt time allocation */ Block* iallocb(int size) { Block *b; ulong addr; int n; if(ialloc.bytes > conf.ialloc){ print("iallocb: limited %lud/%lud\n", ialloc.bytes, conf.ialloc); return 0; } n = sizeof(Block) + size; b = poolalloc(mainmem, n+Hdrspc); if(b == 0){ print("iallocb: no memory %lud/%lud\n", ialloc.bytes, conf.ialloc); return nil; } memset(b, 0, sizeof(Block)); /* align start of data portion by rounding up */ addr = (ulong)b; addr = ROUND(addr + sizeof(Block), BLOCKALIGN); b->base = (uchar*)addr; /* align end of data portion by rounding down */ b->lim = ((uchar*)b) + msize(b); addr = (ulong)(b->lim); addr = addr & ~(BLOCKALIGN-1); b->lim = (uchar*)addr; /* leave sluff at beginning for added headers */ b->rp = b->lim - ROUND(size, BLOCKALIGN); if(b->rp < b->base) panic("allocb"); b->wp = b->rp; b->flag = BINTR; ilock(&ialloc); ialloc.bytes += b->lim - b->base; iunlock(&ialloc); tagwithpc(b, getcallerpc(&size)); return b; } void freeb(Block *b) { void *dead = (void*)Bdead; if(b == nil) return; /* * drivers which perform non cache coherent DMA manage their own buffer * pool of uncached buffers and provide their own free routine. */ if(b->free) { b->free(b); return; } if(b->flag & BINTR) { ilock(&ialloc); ialloc.bytes -= b->lim - b->base; iunlock(&ialloc); } /* poison the block in case someone is still holding onto it */ b->next = dead; b->rp = dead; b->wp = dead; b->lim = dead; b->base = dead; poolfree(mainmem, b); } void checkb(Block *b, char *msg) { void *dead = (void*)Bdead; if(b == dead) panic("checkb b %s %lux", msg, b); if(b->base == dead || b->lim == dead || b->next == dead || b->rp == dead || b->wp == dead){ print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n", b->base, b->lim, b->next); print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp); panic("checkb dead: %s\n", msg); } if(b->base > b->lim) panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); if(b->rp < b->base) panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); if(b->wp < b->base) panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); if(b->rp > b->lim) panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); if(b->wp > b->lim) panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); } void iallocsummary(void) { print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc); . 447,451c if(nv != nil) tagwithpc(nv, getcallerpc(&v)); . 423d 418,421c if(v != nil) . 407,411c if(v != nil) tagwithpc(v, getcallerpc(&size)); . 391,395c tagwithpc(v, getcallerpc(&size)); . 371,375c if(v != nil) tagwithpc(v, getcallerpc(&size)); . 362a static void tagwithpc(void *v, ulong pc) { Bhdr *h; D2B(h, v); B2T(h)->pad = pc; } . ## diffname port/alloc.c 1999/0603 ## diff -e /n/emeliedump/1999/0527/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0603/sys/src/brazil/port/alloc.c 363c void . ## diffname port/alloc.c 1999/0710 ## diff -e /n/emeliedump/1999/0603/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0710/sys/src/brazil/port/alloc.c 542,796d 540d 515,538c u = v; u[-2] = pc; . 496,513c ulong *u; if(v == nil) . 494c tagwithpc(void *v, ulong pc) . 491d 484,489c poolsummary(mainmem); poolsummary(imagmem); . 482c mallocsummary(void) . 480d 466,477c print("%s max %lud cur %lud free %lud alloc %lud\n", p->name, p->maxsize, p->cursize, p->curfree, p->curalloc); . 464c poolsummary(Pool *p) . 462d 459c return mallocz(n*szelem, 1); . 450,453c return poolmsize(mainmem, (uchar*)v-8)-8; . 447c ulong . 431,444c nv = (uchar*)v-8; nsize = size+8; if(l = poolrealloc(mainmem, nv, nsize)) return l+2; return nil; . 427a if(size == 0) { free(v); return nil; } . 426c long nsize; . 424c ulong *l; . 417,418c if(v != nil) { poolfree(mainmem, (uchar*)v-8); } . 409,410d 406c if(size == 0) return nil; v = poolalloc(mainmem, size+8); if(v != nil) { l = v; l[0] = getcallerpc(&size); v = l+2; } . 404a ulong *l; . 396,397d 385,394c v = poolalloc(mainmem, size+8); if(v != nil) { l = v; l[0] = getcallerpc(&size); v = l+2; memset(v, 0, size); . 377,383c if(size == 0) return nil; . 374a ulong *l; . 298,371d 215,295c l = v; l[0] = getcallerpc(&size); v = l+2; memset(v, 0, size); return v; . 189,213c for(;;) { v = poolalloc(mainmem, size+8); if(v != nil) break; tsleep(&up->sleep, return0, 0, 100); . 186,187c void *v; ulong *l; . 184c smalloc(ulong size) . 50,182d 47,48c Pool* mainmem = &pmainmem; Pool* imagmem = &pimagmem; . 34,44c static Pool pimagmem = { .name= "Image", .maxsize= 16*1024*1024, .minarena= 2*1024*1024, .quantum= 32, .alloc= xalloc, .merge= xmerge, .flags= 0, . 9,31c static Pool pmainmem = { .name= "Main", .maxsize= 4*1024*1024, .minarena= 128*1024, .quantum= 32, .alloc= xalloc, .merge= xmerge, .flags= 0, . 7a #include "pool.h" . 4d ## diffname port/alloc.c 1999/0711 ## diff -e /n/emeliedump/1999/0710/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0711/sys/src/brazil/port/alloc.c 75,77d 57,59d ## diffname port/alloc.c 1999/0712 ## diff -e /n/emeliedump/1999/0711/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0712/sys/src/brazil/port/alloc.c 145,146c base = b; ptr = b; limit = B2LIMIT(b); while(base != nil) { print("\tbase #%.8lux ptr #%.8lux", base, ptr); if(ptr->magic == MAGIC_A) print("\tA%.5d\n", ptr->size); else if(ptr->magic == MAGIC_E) print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize); else print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n", ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent); ptr = B2NB(ptr); if(ptr >= limit) { print("link to #%.8lux\n", base->clink); base = base->clink; if(base == nil) break; ptr = base; limit = B2LIMIT(base); } } return; } */ void poolsetparam(char *name, ulong maxsize, int quanta, int chunk, void (*move)(void*, void*)) { Pool *p; int i; for(i=0; iname) == 0){ if(maxsize != 0) p->maxsize = maxsize; if(quanta != 0) p->quanta = quanta; if(chunk != 0) p->chunk = chunk; if(move != nil) p->move = move; return; } } } int poolcompact(Pool *pool) { Bhdr *base, *limit, *ptr, *end, *next; int compacted, recov, nb; if(pool->move == nil || pool->lastfree == pool->nfree) return 0; pool->lastfree = pool->nfree; base = pool->chain; ptr = B2NB(base); /* First Block in arena has clink */ limit = B2LIMIT(base); compacted = 0; pool->root = nil; end = ptr; recov = 0; while(base != nil) { next = B2NB(ptr); if(ptr->magic == MAGIC_A) { if(ptr != end) { memmove(end, ptr, ptr->size); pool->move(B2D(ptr), B2D(end)); recov = (uchar*)ptr - (uchar*)end; compacted = 1; } end = B2NB(end); } if(next >= limit) { nb = (uchar*)limit - (uchar*)end; //print("recovered %d bytes\n", recov); //print("%d bytes at end\n", nb); USED(recov); if(nb > 0){ if(nb < pool->quanta+1) panic("poolcompact: leftover too small\n"); end->size = nb; pooladd(pool, end); } base = base->clink; if(base == nil) break; ptr = B2NB(base); end = ptr; /* could do better by copying between chains */ limit = B2LIMIT(base); recov = 0; } else ptr = next; } return compacted; . 142,143c Bhdr *b, *base, *limit, *ptr; b = p->chain; if(b == nil) . 140c pooldump(Pool *p) . 138a /* . 135,136c int i; for(i = 0; i < table.n; i++) print("Arena: %s cursize=%lud; arenasize=%lud; maxsize=%lud\n", table.pool[i].name, table.pool[i].cursize, table.pool[i].arenasize, table.pool[i].maxsize); . 132a poolshow(void) { int i; for(i = 0; i < table.n; i++) { print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root); pooldump(table.pool[i].root, 0, 'R'); } } */ void . 131a . 128,129c Bhdr *t; if(b == nil) return; print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n", b, b->left, b->right, c, d, b->size, b->fwd, b->prev); d++; for(t = b->fwd; t != b; t = t->fwd) print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd); pooldump(b->left, d, 'l'); pooldump(b->right, d, 'r'); . 126c pooldump(Bhdr *b, int d, int c) . 124a /* . 122c return malloc(n*szelem); . 116c Bhdr *b; D2B(b, v); return b->size - BHDRSIZE; . 106,110c D2B(b, v); osize = b->size - BHDRSIZE; if(osize >= size) return v; nv = poolalloc(mainmem, size); if(nv != nil) { memmove(nv, v, osize); free(v); } if(nv != nil) tagwithpc(nv, getcallerpc(&v)); return nv; . 99,102d 97c int osize; . 95c Bhdr *b; . 87,89c if(v != nil) poolfree(mainmem, v); . 80a if(v != nil) tagwithpc(v, getcallerpc(&size)); . 73,78c v = poolalloc(mainmem, size); . 71d 63a memset(v, 0, size); tagwithpc(v, getcallerpc(&size)); . 62a if(v != nil) tagwithpc(v, getcallerpc(&size)); return v; } void* smalloc(ulong size) { void *v; for(;;) { v = poolalloc(mainmem, size); if(v != nil) break; tsleep(&up->sleep, return0, 0, 100); . 57,61c v = poolalloc(mainmem, size); if(v != nil) . 54d 50a void poolfree(Pool *p, void *v) { Bhdr *b, *c; D2B(b, v); ilock(&p->l); p->nfree++; p->cursize -= b->size; c = B2NB(b); if(c->magic == MAGIC_F) { /* Join forward */ pooldel(p, c); c->magic = 0; b->size += c->size; B2T(b)->hdr = b; } c = B2PT(b)->hdr; if(c->magic == MAGIC_F) { /* Join backward */ pooldel(p, c); b->magic = 0; c->size += b->size; b = c; B2T(b)->hdr = b; } pooladd(p, b); iunlock(&p->l); } int poolread(char *va, int count, ulong offset) { Pool *p; int n, i, signed_off; n = 0; signed_off = offset; for(i = 0; i < table.n; i++) { p = &table.pool[i]; n += snprint(va+n, count-n, "%11lud %11lud %11lud %11d %11d %11d %s\n", p->cursize, p->maxsize, p->hw, p->nalloc, p->nfree, p->nbrk, p->name); if(signed_off > 0) { signed_off -= n; if(signed_off < 0) { memmove(va, va+n+signed_off, -signed_off); n = -signed_off; } else n = 0; } } return n; } void tagwithpc(void *v, ulong pc) { Bhdr *h; D2B(h, v); B2T(h)->pad = pc; } . 44,48c if(q != nil) { pooldel(p, q); q->magic = MAGIC_A; frag = q->size - size; if(frag < (size>>2)) { p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(q); } /* Split */ ns = q->size - size; q->size = size; B2T(q)->hdr = q; t = B2NB(q); t->size = ns; B2T(t)->hdr = t; pooladd(p, t); p->cursize += q->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(q); } ns = p->chunk; if(size > ns) ns = size; ldr = p->quanta+1; alloc = ns+ldr+sizeof(t->magic); p->arenasize += alloc; if(p->arenasize > p->maxsize) { p->arenasize -= alloc; if(poolcompact(p)) { iunlock(&p->l); return poolalloc(p, size); } iunlock(&p->l); print("%s arena too large: size %ld cursize %lud arenasize %lud maxsize %lud\n", p->name, size, p->cursize, p->arenasize, p->maxsize); return nil; } p->nbrk++; t = xalloc(alloc); if(t == nil) { iunlock(&p->l); return nil; } t->magic = MAGIC_E; /* Make a leader */ t->size = ldr; t->csize = ns+ldr; t->clink = p->chain; p->chain = t; B2T(t)->hdr = t; t = B2NB(t); t->magic = MAGIC_A; /* Make the block we are going to return */ t->size = size; B2T(t)->hdr = t; q = t; ns -= size; /* Free the rest */ if(ns > 0) { q = B2NB(t); q->size = ns; B2T(q)->hdr = q; pooladd(p, q); } B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */ p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(t); . 38,42c if(size < 0 || size >= 1024*1024*1024) /* for sanity and to avoid overflow */ return nil; size = (size + BHDRSIZE + p->quanta) & ~(p->quanta); ilock(&p->l); p->nalloc++; t = p->root; q = nil; while(t) { if(t->size == size) { pooldel(p, t); t->magic = MAGIC_A; p->cursize += t->size; if(p->cursize > p->hw) p->hw = p->cursize; iunlock(&p->l); return B2D(t); } if(size < t->size) { q = t; t = t->left; } else t = t->right; . 35,36c Bhdr *q, *t; int alloc, ldr, ns, frag; . 33c poolalloc(Pool *p, long size) . 31a int poolcompact(Pool*); Bhdr* poolchain(Pool *p) { return p->chain; } void pooldel(Pool *p, Bhdr *t) { Bhdr *s, *f, *rp, *q; if(t->parent == nil && p->root != t) { t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->fwd != t) { f = t->fwd; s = t->parent; f->parent = s; if(s == nil) p->root = f; else { if(s->left == t) s->left = f; else s->right = f; } rp = t->left; f->left = rp; if(rp != nil) rp->parent = f; rp = t->right; f->right = rp; if(rp != nil) rp->parent = f; t->prev->fwd = t->fwd; t->fwd->prev = t->prev; return; } if(t->left == nil) rp = t->right; else { if(t->right == nil) rp = t->left; else { f = t; rp = t->right; s = rp->left; while(s != nil) { f = rp; rp = s; s = rp->left; } if(f != t) { s = rp->right; f->left = s; if(s != nil) s->parent = f; s = t->right; rp->right = s; if(s != nil) s->parent = rp; } s = t->left; rp->left = s; s->parent = rp; } } q = t->parent; if(q == nil) p->root = rp; else { if(t == q->left) q->left = rp; else q->right = rp; } if(rp != nil) rp->parent = q; } void pooladd(Pool *p, Bhdr *q) { int size; Bhdr *tp, *t; q->magic = MAGIC_F; q->left = nil; q->right = nil; q->parent = nil; q->fwd = q; q->prev = q; t = p->root; if(t == nil) { p->root = q; return; } size = q->size; tp = nil; while(t != nil) { if(size == t->size) { q->fwd = t->fwd; q->fwd->prev = q; q->prev = t; t->fwd = q; return; } tp = t; if(size < t->size) t = t->left; else t = t->right; } q->parent = tp; if(size < tp->size) tp->left = q; else tp->right = q; } . 29,30c Pool* mainmem = &table.pool[0]; Pool* imagmem = &table.pool[1]; . 19,26c struct { int n; Pool pool[MAXPOOL]; Lock l; } table = { 2, { { "Main", 4*1024*1024, 31, 128*1024 }, { "Image", 16*1024*1024, 31, 2*1024*1024 }, } . 9,16c #define left u.s.bhl #define right u.s.bhr #define fwd u.s.bhf #define prev u.s.bhv #define parent u.s.bhp struct Pool { char* name; ulong maxsize; int quanta; int chunk; ulong cursize; ulong arenasize; ulong hw; Lock l; Bhdr* root; Bhdr* chain; int nalloc; int nfree; int nbrk; int lastfree; void (*move)(void*, void*); . 7d 3a #include "pool.h" . ## diffname port/alloc.c 1999/0713 ## diff -e /n/emeliedump/1999/0712/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0713/sys/src/brazil/port/alloc.c 515,616c u = v; u[-2] = pc; . 510,513c ulong *u; if(v == nil) . 508c tagwithpc(void *v, ulong pc) . 506d 496,503c poolsummary(mainmem); poolsummary(imagmem); . 482,493d 480d 466,477c print("%s max %lud cur %lud free %lud alloc %lud\n", p->name, p->maxsize, p->cursize, p->curfree, p->curalloc); . 464c poolsummary(Pool *p) . 462d 459c return mallocz(n*szelem, 1); . 450,453c return poolmsize(mainmem, (uchar*)v-8)-8; . 431,444c nv = (uchar*)v-8; nsize = size+8; if(l = poolrealloc(mainmem, nv, nsize)) return l+2; return nil; . 427a if(size == 0) { free(v); return nil; } . 426c long nsize; . 424c ulong *l; . 417,418c if(v != nil) { if(0) if(mainmem->flags & POOL_STUPID) { print("A"); delay(50); } poolfree(mainmem, (uchar*)v-8); if(0) if(mainmem->flags & POOL_STUPID) { print("a"); delay(50); } } . 409,410d 406c v = poolalloc(mainmem, size+8); if(v != nil) { l = v; l[0] = getcallerpc(&size); v = l+2; } . 404a ulong *l; . 396,397d 380,394d 377,378c v = poolalloc(mainmem, size+8); if(v != nil) { l = v; l[0] = getcallerpc(&size); v = l+2; . 374a ulong *l; . 298,371d 215,295c l = v; l[0] = getcallerpc(&size); v = l+2; memset(v, 0, size); return v; . 189,213c for(;;) { v = poolalloc(mainmem, size+8); if(v != nil) break; tsleep(&up->sleep, return0, 0, 100); . 186,187c void *v; ulong *l; . 184c smalloc(ulong size) . 50,182d 47,48c Pool* mainmem = &pmainmem; Pool* imagmem = &pimagmem; . 34,44c static Pool pimagmem = { .name= "Image", .maxsize= 16*1024*1024, .minarena= 2*1024*1024, .quantum= 32, .alloc= xalloc, .merge= xmerge, .flags= 0, . 15,31c static Pool pmainmem = { .name= "Main", .maxsize= 4*1024*1024, .minarena= 128*1024, .quantum= 32, .alloc= xalloc, .merge= xmerge, .flags= 0, . 9,13c enum { POOL_STUPID = 0x80000000, }; . 7a #include "pool.h" . 4d ## diffname port/alloc.c 1999/0714 ## diff -e /n/emeliedump/1999/0713/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0714/sys/src/brazil/port/alloc.c 160a ulong getmalloctag(void *v) { USED(v); if(Npadlong <= MallocOffset) return ~0; return ((ulong*)v)[-Npadlong+MallocOffset]; } ulong getrealloctag(void *v) { USED(v); if(Npadlong <= ReallocOffset) return ((ulong*)v)[-Npadlong+ReallocOffset]; return ~0; } . 158c u[-Npadlong+ReallocOffset] = pc; . 155c USED(v, pc); if(Npadlong <= ReallocOffset || v == nil) . 147,153d 145c setrealloctag(void *v, ulong pc) . 140,141c ulong *u; USED(v, pc); if(Npadlong <= MallocOffset || v == nil) return; u = v; u[-Npadlong+MallocOffset] = pc; . 138c setmalloctag(void *v, ulong pc) . 134c void *v; if(v = mallocz(n*szelem, 1)) setmalloctag(v, getcallerpc(&n)); return v; . 128c return poolmsize(mainmem, (ulong*)v-Npadlong)-Npadlong*sizeof(ulong); . 118,122c if(nv = poolrealloc(mainmem, v, size)){ nv = (ulong*)nv+Npadlong; setrealloctag(nv, getcallerpc(&v)); if(v == nil) setmalloctag(nv, getcallerpc(&v)); } return nv; . 111,116c if(v != nil) v = (ulong*)v-Npadlong; if(Npadlong !=0 && size != 0) size += Npadlong*sizeof(ulong); . 109d 107d 91,101c if(v != nil) poolfree(mainmem, (ulong*)v-Npadlong); . 77,81c v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); if(Npadlong && v != nil){ v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); setrealloctag(v, 0); . 75d 61,65c v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); if(Npadlong && v != nil) { v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); setrealloctag(v, 0); . 58d 48,50c if(Npadlong){ v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); } . 43c v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); . 40d 35a /* * because we can't print while we're holding the locks, * we have the save the message and print it once we let go. */ static void poolprint(Pool *p, char *fmt, ...) { va_list v; int n; va_start(v, fmt); n = doprint(p->msg, p->msg+sizeof p->msg, fmt, v)-p->msg; va_end(v); if(n >= sizeof p->msg); n = sizeof(p->msg)-1; if(n < 0) n = 0; p->msg[n] = 0; } static void ppanic(Pool *p, char *fmt, ...) { va_list v; int n; va_start(v, fmt); n = doprint(p->msg, p->msg+sizeof p->msg, fmt, v)-p->msg; va_end(v); if(n >= sizeof p->msg); n = sizeof(p->msg)-1; if(n < 0) n = 0; p->msg[n] = 0; iunlock(&p->lk); panic("%s", p->msg); } static void plock(Pool *p) { ilock(&p->lk); p->msg[0] = 0; } static void punlock(Pool *p) { char msg[sizeof p->msg]; if(p->msg[0] == 0){ iunlock(&p->lk); return; } memmove(msg, p->msg, sizeof msg); iunlock(&p->lk); print("%.*s", sizeof p->msg, msg); } void poolsummary(Pool *p) { print("%s max %lud cur %lud free %lud alloc %lud\n", p->name, p->maxsize, p->cursize, p->curfree, p->curalloc); } void mallocsummary(void) { poolsummary(mainmem); poolsummary(imagmem); } /* everything from here down should be the same in libc, libdebugmalloc, and the kernel */ /* - except the code for malloc(), which alternately doesn't clear or does. */ /* - except the code for smalloc(), which lives only in the kernel. */ /* * Npadlong is the number of 32-bit longs to leave at the beginning of * each allocated buffer for our own bookkeeping. We return to the callers * a pointer that points immediately after our bookkeeping area. Incoming pointers * must be decremented by that much, and outgoing pointers incremented. * The malloc tag is stored at MallocOffset from the beginning of the block, * and the realloc tag at ReallocOffset. The offsets are from the true beginning * of the block, not the beginning the caller sees. * * The extra if(Npadlong != 0) in various places is a hint for the compiler to * compile out function calls that would otherwise be no-ops. */ /* non tracing * enum { Npadlong = 0, MallocOffset = 0, ReallocOffset = 0, }; * */ /* tracing */ enum { Npadlong = 2, MallocOffset = 0, ReallocOffset = 1 }; . 30a .lock= plock, .unlock= punlock, .print= poolprint, .panic= ppanic, . 20c .flags= POOL_TOLERANCE, .lock= plock, .unlock= punlock, .print= poolprint, .panic= ppanic, . 9,11c static void poolprint(Pool*, char*, ...); static void ppanic(Pool*, char*, ...); static void plock(Pool*); static void punlock(Pool*); . ## diffname port/alloc.c 1999/0825 ## diff -e /n/emeliedump/1999/0714/sys/src/brazil/port/alloc.c /n/emeliedump/1999/0825/sys/src/brazil/port/alloc.c 102,104c memmove(msg, pv->msg, sizeof msg); iunlock(&pv->lk); print("%.*s", sizeof pv->msg, msg); . 97,98c pv = p->private; if(pv->msg[0] == 0){ iunlock(&pv->lk); . 95c Private *pv; char msg[sizeof pv->msg]; . 88,89c Private *pv; pv = p->private; ilock(&pv->lk); pv->msg[0] = 0; . 80,82c pv->msg[n] = 0; iunlock(&pv->lk); panic("%s", pv->msg); . 76,77c if(n >= sizeof pv->msg); n = sizeof(pv->msg)-1; . 74c n = doprint(pv->msg, pv->msg+sizeof pv->msg, fmt, v)-pv->msg; . 72a pv = p->private; . 71a Private *pv; . 64c pv->msg[n] = 0; . 60,61c if(n >= sizeof pv->msg); n = sizeof(pv->msg)-1; . 58c n = doprint(pv->msg, pv->msg+sizeof pv->msg, fmt, v)-pv->msg; . 56a pv = p->private; . 55a Private *pv; . 41a .private= &pimagpriv, . 28a static Private pimagpriv; . 26a .private= &pmainpriv, . 13a typedef struct Private Private; struct Private { Lock lk; char msg[128]; /* a rock for messages to be printed at unlock */ }; static Private pmainpriv; . 7c #include . ## diffname port/alloc.c 2000/0120 ## diff -e /n/emeliedump/1999/0825/sys/src/brazil/port/alloc.c /n/emeliedump/2000/0120/sys/src/9/port/alloc.c 98c panic("%s", msg); . 92,96c memmove(msg, pv->msg, sizeof msg); . 90c doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); . 86a char msg[sizeof pv->msg]; . 74,78d 72c doprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); . 17c char msg[256]; /* a rock for messages to be printed at unlock */ . ## diffname port/alloc.c 2000/0229 ## diff -e /n/emeliedump/2000/0120/sys/src/9/port/alloc.c /n/emeliedump/2000/0229/sys/src/9/port/alloc.c 67d ## diffname port/alloc.c 2000/0407 ## diff -e /n/emeliedump/2000/0229/sys/src/9/port/alloc.c /n/emeliedump/2000/0407/sys/src/9/port/alloc.c 79d ## diffname port/alloc.c 2002/0217 ## diff -e /n/emeliedump/2000/0407/sys/src/9/port/alloc.c /n/emeliedump/2002/0217/sys/src/9/port/alloc.c 84c vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); . 71c vseprint(pv->msg+strlen(pv->msg), pv->msg+sizeof pv->msg, fmt, v); . ## diffname port/alloc.c 2002/0425 ## diff -e /n/emeliedump/2002/0217/sys/src/9/port/alloc.c /n/emeliedump/2002/0425/sys/src/9/port/alloc.c 197a memset(v, 0, size); . 196d 192c if(v == nil) return nil; if(Npadlong){ .