ref: cff48f4e1decb6e93941773ee325873c23c03a29
parent: 0c14944a32c45861183ab18f9ac98388e7bb4f3a
author: joe9 <joe9mail@gmail.com>
date: Mon Jul 5 08:05:17 EDT 2021
changes to include allocpc and reallocpc in Bhdr
--- /dev/null
+++ b/emu/port/alloc.c_without_Npadlong
@@ -1,0 +1,1017 @@
+#include "dat.h"
+#include "fns.h"
+#include "interp.h"
+#include "error.h"
+
+enum
+{
+ MAXPOOL = 4
+};
+
+#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
+
+#define RESERVED 512*1024
+
+struct Pool
+{
+ char* name;
+ int pnum;
+ ulong maxsize;
+ int quanta;
+ int chunk;
+ int monitor;
+ ulong ressize; /* restricted size */
+ ulong cursize;
+ ulong arenasize;
+ ulong hw;
+ Lock l;
+ Bhdr* root;
+ Bhdr* chain;
+ ulong nalloc;
+ ulong nfree;
+ int nbrk;
+ int lastfree;
+ void (*move)(void*, void*);
+};
+
+void* initbrk(ulong);
+
+/* keep the quanta above the size of 5 pointers and 2 longs else the next block
+ will be getting overwritten by the header -- starts a corruption hunt
+ when pointer size = 8 bytes, then 63 = 2^q -1
+ for 4 bytes, 31
+ TODO make this a macro?
+ for allocpc and reallocpc, 2 * 8 = 16 bytes get added
+ so, minimum size = 2*4 + 2*8 + 5*8 = 64, using 127 to satisfy 2^q -1
+ */
+struct
+{
+ int n;
+ Pool pool[MAXPOOL];
+ /* Lock l; */
+} table = {
+ 3,
+ {
+ { "main", 0, 32*1024*1024, 127, 512*1024, 0, 31*1024*1024 },
+ { "heap", 1, 32*1024*1024, 127, 512*1024, 0, 31*1024*1024 },
+ { "image", 2, 64*1024*1024+256, 127, 4*1024*1024, 1, 63*1024*1024 },
+ }
+};
+
+Pool* mainmem = &table.pool[0];
+Pool* heapmem = &table.pool[1];
+Pool* imagmem = &table.pool[2];
+
+static void _auditmemloc(char *, void *);
+void (*auditmemloc)(char *, void *) = _auditmemloc;
+static void _poolfault(void *, char *, uintptr);
+void (*poolfault)(void *, char *, uintptr) = _poolfault;
+void pooldump(Pool *p);
+
+enum {
+ Monitor = 1
+};
+
+void (*memmonitor)(int, uintptr, void *, ulong) = nil;
+#define MM(v,pc,base,size) if(!Monitor || memmonitor==nil){} else memmonitor((v),(pc),(base),(size))
+
+#define CKLEAK 0
+int ckleak;
+#define ML(v, sz, pc) if(CKLEAK && ckleak && v){ if(sz) fprint(2, "%zx %zd %zx\n", (uintptr)v, (uintptr)sz, (uintptr)pc); else fprint(2, "%zx\n", (uintptr)v); }
+
+int
+memusehigh(void)
+{
+ return mainmem->cursize > mainmem->ressize ||
+ heapmem->cursize > heapmem->ressize ||
+ 0 && imagmem->cursize > imagmem->ressize;
+}
+
+int
+memlow(void)
+{
+ return heapmem->cursize > (heapmem->maxsize)/2;
+}
+
+int
+poolsetsize(char *s, int size)
+{
+ int i;
+
+ for(i = 0; i < table.n; i++) {
+ if(strcmp(table.pool[i].name, s) == 0) {
+ table.pool[i].maxsize = size;
+ table.pool[i].ressize = size-RESERVED;
+ if(size < RESERVED)
+ panic("not enough memory");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+poolimmutable(void *v)
+{
+ Bhdr *b;
+
+ D2B(b, v);
+ b->magic = MAGIC_I;
+}
+
+void
+poolmutable(void *v)
+{
+ Bhdr *b;
+
+ D2B(b, v);
+ b->magic = MAGIC_A;
+ ((Heap*)v)->color = mutator;
+}
+
+char*
+poolname(Pool *p)
+{
+ return p->name;
+}
+
+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->prev = t->prev;
+ q->prev->fwd = q;
+ q->fwd = t;
+ t->prev = 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;
+}
+
+static void*
+dopoolalloc(Pool *p, u32 asize, uintptr pc)
+{
+ Bhdr *q, *t;
+ int alloc, ldr, ns, frag;
+ int osize, size;
+
+ if(asize >= 1024*1024*1024) /* for sanity and to avoid overflow */
+ return nil;
+ size = asize;
+ osize = size;
+ size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
+
+ lock(&p->l);
+ p->nalloc++;
+
+ t = p->root;
+ q = nil;
+ while(t) {
+ if(t->size == size) {
+ t = t->fwd;
+ pooldel(p, t);
+ t->magic = MAGIC_A;
+ p->cursize += t->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ unlock(&p->l);
+ if(p->monitor)
+ MM(p->pnum, pc, B2D(t), size);
+/*if(p->pnum == 0) print("pool %s size %d maxsize %lud quanta %d chunk %d"
+ " ressize %lud cursize %lud arenasize %lud caller 0x%p\n",
+ p->name, size, p->maxsize, p->quanta, p->chunk,
+ p->ressize, p->cursize, p->arenasize, pc);*/
+ return B2D(t);
+ }
+ if(size < t->size) {
+ q = t;
+ t = t->left;
+ }
+ else
+ t = t->right;
+ }
+ if(q != nil) {
+ pooldel(p, q);
+ q->magic = MAGIC_A;
+ frag = q->size - size;
+ if(frag < (size>>2) && frag < 0x8000) {
+ p->cursize += q->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ unlock(&p->l);
+ if(p->monitor)
+ MM(p->pnum, pc, B2D(q), size);
+ 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;
+ unlock(&p->l);
+ if(p->monitor)
+ MM(p->pnum, pc, B2D(q), size);
+ return B2D(q);
+ }
+
+ ns = p->chunk;
+ if(size > ns)
+ ns = size;
+ ldr = p->quanta+1;
+
+ alloc = ns+ldr+ldr;
+ p->arenasize += alloc;
+ if(p->arenasize > p->maxsize) {
+ p->arenasize -= alloc;
+ ns = p->maxsize-p->arenasize-ldr-ldr;
+ ns &= ~p->quanta;
+ if (ns < size) {
+ if(poolcompact(p)) {
+ unlock(&p->l);
+ return poolalloc(p, osize);
+ }
+
+ unlock(&p->l);
+ print("arena %s too large: size %d maxsize %lud ressize %lud"
+ " cursize %lud arenasize %lud\n",
+ p->name, size, p->maxsize, p->ressize,
+ p->cursize, p->arenasize);
+ return nil;
+ }
+ alloc = ns+ldr+ldr;
+ p->arenasize += alloc;
+ }
+
+ p->nbrk++;
+ t = (Bhdr *)sbrk(alloc);
+ if(t == (void*)-1) {
+ p->nbrk--;
+ unlock(&p->l);
+ return nil;
+ }
+#ifdef __NetBSD__
+ /* Align allocations to 16 bytes */
+ {
+ const size_t off = __builtin_offsetof(struct Bhdr, u.data)
+ + Npadlong*sizeof(ulong);
+ struct assert_align {
+ unsigned int align_ok : (off % 8 == 0) ? 1 : -1;
+ };
+
+ const ulong align = (off - 1) % 16;
+ t = (Bhdr *)(((ulong)t + align) & ~align);
+ }
+#else
+ /* Double alignment */
+ t = (Bhdr *)(((uintptr)t + 7) & ~7);
+#endif
+ if(p->chain != nil && (char*)t-(char*)B2LIMIT(p->chain)-ldr == 0){
+ /* can merge chains */
+ if(0)print("merging chains %p and %p in %s\n", p->chain, t, p->name);
+ q = B2LIMIT(p->chain);
+ q->magic = MAGIC_A;
+ q->size = alloc;
+ B2T(q)->hdr = q;
+ t = B2NB(q);
+ t->magic = MAGIC_E;
+ p->chain->csize += alloc;
+ p->cursize += alloc;
+ unlock(&p->l);
+ poolfree(p, B2D(q)); /* for backward merge */
+ return poolalloc(p, osize);
+ }
+
+ 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;
+ unlock(&p->l);
+ if(p->monitor)
+ MM(p->pnum, pc, B2D(t), size);
+ return B2D(t);
+}
+
+void *
+poolalloc(Pool *p, ulong asize)
+{
+ Prog *prog;
+
+ if(p->cursize > p->ressize && (prog = currun()) != nil && prog->flags&Prestricted)
+ return nil;
+ return dopoolalloc(p, asize, getcallerpc(&p));
+}
+
+void
+poolfree(Pool *p, void *v)
+{
+ Bhdr *b, *c;
+ extern Bhdr *ptr;
+
+ D2B(b, v);
+ if(p->monitor)
+ MM(p->pnum|(1<<8), getcallerpc(&p), v, b->size);
+
+ lock(&p->l);
+ p->nfree++;
+ p->cursize -= b->size;
+ c = B2NB(b);
+ if(c->magic == MAGIC_F) { /* Join forward */
+ if(c == ptr)
+ ptr = b;
+ 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 */
+ if(b == ptr)
+ ptr = c;
+ pooldel(p, c);
+ b->magic = 0;
+ c->size += b->size;
+ b = c;
+ B2T(b)->hdr = b;
+ }
+ pooladd(p, b);
+ unlock(&p->l);
+}
+
+void *
+poolrealloc(Pool *p, void *v, ulong size)
+{
+ Bhdr *b;
+ void *nv;
+ int osize;
+
+ if(size >= 1024*1024*1024) /* for sanity and to avoid overflow */
+ return nil;
+ if(size == 0){
+ poolfree(p, v);
+ return nil;
+ }
+ SET(osize);
+ if(v != nil){
+ lock(&p->l);
+ D2B(b, v);
+ osize = b->size - BHDRSIZE;
+ unlock(&p->l);
+ if(osize >= size)
+ return v;
+ }
+ nv = poolalloc(p, size);
+ if(nv != nil && v != nil){
+ memmove(nv, v, osize);
+ poolfree(p, v);
+ }
+ return nv;
+}
+
+ulong
+poolmsize(Pool *p, void *v)
+{
+ Bhdr *b;
+ ulong size;
+
+ if(v == nil)
+ return 0;
+ lock(&p->l);
+ D2B(b, v);
+ size = b->size - BHDRSIZE;
+ unlock(&p->l);
+ return size;
+}
+
+static ulong
+poolmax(Pool *p)
+{
+ Bhdr *t;
+ ulong size;
+
+ lock(&p->l);
+ size = p->maxsize - p->cursize;
+ t = p->root;
+ if(t != nil) {
+ while(t->right != nil)
+ t = t->right;
+ if(size < t->size)
+ size = t->size;
+ }
+ if(size >= BHDRSIZE)
+ size -= BHDRSIZE;
+ unlock(&p->l);
+ return size;
+}
+
+ulong
+poolmaxsize(void)
+{
+ int i;
+ ulong total;
+
+ total = 0;
+ for(i = 0; i < nelem(table.pool); i++)
+ total += table.pool[i].maxsize;
+ return total;
+}
+
+int
+poolread(char *va, int count, uintptr 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 %11lud %11lud %11d %11lud %s\n",
+ p->cursize,
+ p->maxsize,
+ p->hw,
+ p->nalloc,
+ p->nfree,
+ p->nbrk,
+ poolmax(p),
+ 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*
+smalloc(size_t size)
+{
+ void *v;
+
+ for(;;){
+ v = malloc(size);
+ if(v != nil)
+ break;
+ if(0)
+ print("smalloc waiting from %zx\n", getcallerpc(&size));
+ osenter();
+ osmillisleep(100);
+ osleave();
+ }
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ return v;
+}
+
+void*
+kmalloc(size_t size)
+{
+ void *v;
+
+ v = dopoolalloc(mainmem, size, getcallerpc(&size));
+ if(v != nil){
+ ML(v, size, getcallerpc(&size));
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ memset(v, 0, size);
+ MM(0, getcallerpc(&size), v, size);
+ } else {
+ print("kmalloc failed from %zx\n", getcallerpc(&size));
+ }
+ return v;
+}
+
+void*
+malloc(size_t size)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size);
+ if(v != nil){
+ ML(v, size, getcallerpc(&size));
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ memset(v, 0, size);
+ MM(0, getcallerpc(&size), v, size);
+ } else {
+ print("malloc failed from %zx\n", getcallerpc(&size));
+ }
+ return v;
+}
+
+void*
+mallocz(ulong size, int clr)
+{
+ void *v;
+
+ v = poolalloc(mainmem, size);
+ if(v != nil){
+ ML(v, size, getcallerpc(&size));
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ if(clr)
+ memset(v, 0, size);
+ MM(0, getcallerpc(&size), v, size);
+ } else{
+ print("mallocz failed from %zx\n", getcallerpc(&size));
+ }
+ return v;
+}
+
+void
+free(void *v)
+{
+ Bhdr *b;
+
+ if(v != nil) {
+ D2B(b, v);
+ ML(v, 0, 0);
+ MM(1<<8|0, getcallerpc(&v), v, b->size);
+ poolfree(mainmem, v);
+ }
+}
+
+void*
+realloc(void *v, size_t size)
+{
+ void *nv;
+
+ if(size == 0)
+ return malloc(size); /* temporary change until realloc calls can be checked */
+ nv = poolrealloc(mainmem, v, size);
+ ML(v, 0, 0);
+ ML(nv, size, getcallerpc(&v));
+ if(nv != nil) {
+ setrealloctag(nv, getcallerpc(&v));
+ if(v == nil)
+ setmalloctag(v, getcallerpc(&v));
+ } else {
+ print("realloc failed from %zx\n", getcallerpc(&v));
+ }
+ return nv;
+}
+
+void
+setmalloctag(void *v, uintptr pc)
+{
+ Bhdr *b;
+
+ if(v != nil){
+ D2B(b, v);
+ b->allocpc = pc;
+ }
+}
+
+uintptr
+getmalloctag(void *v)
+{
+ Bhdr *b;
+
+ if(v == nil)
+ abort();
+ D2B(b, v);
+ return b->allocpc;
+}
+
+void
+setrealloctag(void *v, uintptr pc)
+{
+ Bhdr *b;
+
+ if(v != nil){
+ D2B(b, v);
+ b->reallocpc = pc;
+ }
+}
+
+uintptr
+getrealloctag(void *v)
+{
+ Bhdr *b;
+
+ if(v == nil)
+ abort();
+ D2B(b, v);
+ return b->reallocpc;
+}
+
+ulong
+msize(void *v)
+{
+ if(v == nil)
+ return 0;
+ return poolmsize(mainmem, v);
+}
+
+void*
+calloc(size_t n, size_t szelem)
+{
+ return malloc(n*szelem);
+}
+
+void
+pooldump(Pool *p)
+{
+ Bhdr *b, *base, *limit, *ptr;
+
+ b = p->chain;
+ if(b == nil)
+ return;
+ base = b;
+ ptr = b;
+ limit = B2LIMIT(b);
+
+ while(base != nil) {
+ print("\tbase #%.8p ptr #%.8p", base, ptr);
+ if(ptr->magic == MAGIC_A || ptr->magic == MAGIC_I)
+ print("\tA%.5d pc 0x%p\n", ptr->size, getmalloctag(ptr));
+ else if(ptr->magic == MAGIC_E)
+ print("\tE\tL#%.8p\tS#%.8lx\n", ptr->clink, ptr->csize);
+ else
+ print("\tF%.5d\tL#%.8p\tR#%.8p\tF#%.8p\tP#%.8p\tT#%.8p\n",
+ ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
+ ptr = B2NB(ptr);
+ if(ptr >= limit) {
+ print("link to #%.8p\n", base->clink);
+ base = base->clink;
+ if(base == nil)
+ break;
+ ptr = base;
+ limit = B2LIMIT(base);
+ }
+ }
+}
+
+void
+poolsetcompact(Pool *p, void (*move)(void*, void*))
+{
+ p->move = move;
+}
+
+int
+poolcompact(Pool *pool)
+{
+ Bhdr *base, *limit, *ptr, *end, *next;
+ int compacted, 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;
+ while(base != nil) {
+ next = B2NB(ptr);
+ if(ptr->magic == MAGIC_A || ptr->magic == MAGIC_I) {
+ if(ptr != end) {
+ memmove(end, ptr, ptr->size);
+ pool->move(B2D(ptr), B2D(end));
+ compacted = 1;
+ }
+ end = B2NB(end);
+ }
+ if(next >= limit) {
+ nb = (uchar*)limit - (uchar*)end;
+ if(nb > 0){
+ if(nb < pool->quanta+1){
+ print("poolcompact: leftover too small\n");
+ abort();
+ }
+ end->size = nb;
+ B2T(end)->hdr = end;
+ 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);
+ } else
+ ptr = next;
+ }
+
+ return compacted;
+}
+
+static void
+_poolfault(void *v, char *msg, uintptr c)
+{
+ auditmemloc(msg, v);
+ panic("%s %lux (from %lux/%lux)", msg, v, getcallerpc(&v), c);
+}
+
+static void
+dumpvl(char *msg, uintptr *v, int n)
+{
+ int i, l;
+
+ l = print("%s at %p: ", msg, v);
+ for (i = 0; i < n; i++) {
+ if (l >= 60) {
+ print("\n");
+ l = print(" %p: ", v);
+ }
+ l += print(" %zx", *v++);
+ }
+ print("\n");
+}
+
+static void
+corrupted(char *str, char *msg, Pool *p, Bhdr *b, void *v)
+{
+ print("%s(%p): pool %s CORRUPT: %s at %p'%ud(magic=%ux)\n",
+ str, v, p->name, msg, b, b->size, b->magic);
+ dumpvl("bad Bhdr", (uintptr *)((uintptr)b & ~3)-4, 10);
+}
+
+static void
+_auditmemloc(char *str, void *v)
+{
+ Pool *p;
+ Bhdr *bc, *ec, *b, *nb, *fb = nil;
+ char *fmsg, *msg;
+ ulong fsz;
+
+ SET(fsz);
+ SET(fmsg);
+ for (p = &table.pool[0]; p < &table.pool[nelem(table.pool)]; p++) {
+ lock(&p->l);
+ for (bc = p->chain; bc != nil; bc = bc->clink) {
+ if (bc->magic != MAGIC_E) {
+ unlock(&p->l);
+ corrupted(str, "chain hdr!=MAGIC_E", p, bc, v);
+ goto nextpool;
+ }
+ ec = B2LIMIT(bc);
+ if (((Bhdr*)v >= bc) && ((Bhdr*)v < ec))
+ goto found;
+ }
+ unlock(&p->l);
+nextpool: ;
+ }
+ print("%s: %p not in pools\n", str, v);
+ return;
+
+found:
+ for (b = bc; b < ec; b = nb) {
+ switch(b->magic) {
+ case MAGIC_F:
+ msg = "free blk";
+ break;
+ case MAGIC_I:
+ msg = "immutable block";
+ break;
+ case MAGIC_A:
+ msg = "block";
+ break;
+ default:
+ if (b == bc && b->magic == MAGIC_E) {
+ msg = "pool hdr";
+ break;
+ }
+ unlock(&p->l);
+ corrupted(str, "bad magic", p, b, v);
+ goto badchunk;
+ }
+ if (b->size <= 0 || (b->size & p->quanta)) {
+ unlock(&p->l);
+ corrupted(str, "bad size", p, b, v);
+ goto badchunk;
+ }
+ if (fb != nil)
+ break;
+ nb = B2NB(b);
+ if ((Bhdr*)v < nb) {
+ fb = b;
+ fsz = b->size;
+ fmsg = msg;
+ }
+ }
+ unlock(&p->l);
+ if (b >= ec) {
+ if (b > ec)
+ corrupted(str, "chain size mismatch", p, b, v);
+ else if (b->magic != MAGIC_E)
+ corrupted(str, "chain end!=MAGIC_E", p, b, v);
+ }
+badchunk:
+ if (fb != nil) {
+ print("%s: %p in %s:", str, v, p->name);
+ if (fb == v)
+ print(" is %s '%lux\n", fmsg, fsz);
+ else
+ print(" in %s at %p'%lux\n", fmsg, fb, fsz);
+ dumpvl("area", (uintptr *)((uintptr)v & ~3)-4, 20);
+ }
+}
+
+char *
+poolaudit(char*(*audit)(int, Bhdr *))
+{
+ Pool *p;
+ Bhdr *bc, *ec, *b;
+ char *r = nil;
+
+ for (p = &table.pool[0]; p < &table.pool[nelem(table.pool)]; p++) {
+ lock(&p->l);
+ for (bc = p->chain; bc != nil; bc = bc->clink) {
+ if (bc->magic != MAGIC_E) {
+ unlock(&p->l);
+ return "bad chain hdr";
+ }
+ ec = B2LIMIT(bc);
+ for (b = bc; b < ec; b = B2NB(b)) {
+ if (b->size <= 0 || (b->size & p->quanta))
+ r = "bad size in bhdr";
+ else
+ switch(b->magic) {
+ case MAGIC_E:
+ if (b != bc) {
+ r = "unexpected MAGIC_E";
+ break;
+ }
+ case MAGIC_F:
+ case MAGIC_A:
+ case MAGIC_I:
+ r = audit(p->pnum, b);
+ break;
+ default:
+ r = "bad magic";
+ }
+ if (r != nil) {
+ unlock(&p->l);
+ return r;
+ }
+ }
+ if (b != ec || b->magic != MAGIC_E) {
+ unlock(&p->l);
+ return "bad chain ending";
+ }
+ }
+ unlock(&p->l);
+ }
+ return r;
+}
--- /dev/null
+++ b/include/fcall.h_without_ulong
@@ -1,0 +1,140 @@
+#pragma src "/usr/inferno/lib9"
+#pragma lib "libc.a"
+
+#define VERSION9P "9P2000"
+
+#define MAXWELEM 16
+
+typedef
+struct Fcall
+{
+ uchar type;
+ u32 fid;
+ ushort tag;
+ /* union { */
+ /* struct { */
+ u32 msize; /* Tversion, Rversion */
+ char *version; /* Tversion, Rversion */
+ /* }; */
+ /* struct { */
+ ushort oldtag; /* Tflush */
+ /* }; */
+ /* struct { */
+ char *ename; /* Rerror */
+ /* }; */
+ /* struct { */
+ Qid qid; /* Rattach, Ropen, Rcreate */
+ u32 iounit; /* Ropen, Rcreate */
+ /* }; */
+ /* struct { */
+ Qid aqid; /* Rauth */
+ /* }; */
+ /* struct { */
+ u32 afid; /* Tauth, Tattach */
+ char *uname; /* Tauth, Tattach */
+ char *aname; /* Tauth, Tattach */
+ /* }; */
+ /* struct { */
+ u32 perm; /* Tcreate */
+ char *name; /* Tcreate */
+ uchar mode; /* Tcreate, Topen */
+ /* }; */
+ /* struct { */
+ u32 newfid; /* Twalk */
+ ushort nwname; /* Twalk */
+ char *wname[MAXWELEM]; /* Twalk */
+ /* }; */
+ /* struct { */
+ ushort nwqid; /* Rwalk */
+ Qid wqid[MAXWELEM]; /* Rwalk */
+ /* }; */
+ /* struct { */
+ s64 offset; /* Tread, Twrite */
+ u32 count; /* Tread, Twrite, Rread */
+ char *data; /* Twrite, Rread */
+ /* }; */
+ /* struct { */
+ ushort nstat; /* Twstat, Rstat */
+ uchar *stat; /* Twstat, Rstat */
+ /* }; */
+ /* }; */
+} Fcall;
+
+
+#define GBIT8(p) ((p)[0])
+#define GBIT16(p) ((p)[0]|((p)[1]<<8))
+#define GBIT32(p) ((u32)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)))
+#define GBIT64(p) ((u32)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\
+ ((s64)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32))
+
+#define PBIT8(p,v) (p)[0]=(v)
+#define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8
+#define PBIT32(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24
+#define PBIT64(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24;\
+ (p)[4]=(v)>>32;(p)[5]=(v)>>40;(p)[6]=(v)>>48;(p)[7]=(v)>>56
+
+#define BIT8SZ 1
+#define BIT16SZ 2
+#define BIT32SZ 4
+#define BIT64SZ 8
+#define QIDSZ (BIT8SZ+BIT32SZ+BIT64SZ)
+
+/* STATFIXLEN includes leading 16-bit count */
+/* The count, however, excludes itself; total size is BIT16SZ+count */
+#define STATFIXLEN (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ) /* amount of fixed length data in a stat buffer */
+
+#define NOTAG (u16)~0U /* Dummy tag */
+#define NOFID (u32)~0U /* Dummy fid */
+#define IOHDRSZ 24 /* ample room for Twrite/Rread header (iounit) */
+
+enum
+{
+ Tversion = 100,
+ Rversion,
+ Tauth = 102,
+ Rauth,
+ Tattach = 104,
+ Rattach,
+ Terror = 106, /* illegal */
+ Rerror,
+ Tflush = 108,
+ Rflush,
+ Twalk = 110,
+ Rwalk,
+ Topen = 112,
+ Ropen,
+ Tcreate = 114,
+ Rcreate,
+ Tread = 116,
+ Rread,
+ Twrite = 118,
+ Rwrite,
+ Tclunk = 120,
+ Rclunk,
+ Tremove = 122,
+ Rremove,
+ Tstat = 124,
+ Rstat,
+ Twstat = 126,
+ Rwstat,
+ Tmax,
+};
+
+uint convM2S(uchar*, uint, Fcall*);
+uint convS2M(Fcall*, uchar*, uint);
+uint sizeS2M(Fcall*);
+
+int statcheck(uchar *abuf, uint nbuf);
+uint convM2D(uchar*, uint, Dir*, char*);
+uint convD2M(Dir*, uchar*, uint);
+uint sizeD2M(Dir*);
+
+int fcallfmt(Fmt*);
+int dirfmt(Fmt*);
+int dirmodefmt(Fmt*);
+
+int read9pmsg(int, void*, uint);
+
+#pragma varargck type "F" Fcall*
+#pragma varargck type "M" ulong
+#pragma varargck type "D" Dir*
--- /dev/null
+++ b/include/pool.h_without_Npadlong
@@ -1,0 +1,76 @@
+/* Inferno tree allocator */
+
+typedef struct Pool Pool;
+typedef struct Bhdr Bhdr;
+typedef struct Btail Btail;
+
+#pragma incomplete Pool
+
+enum
+{
+ MAGIC_A = 0xa110c, /* Allocated block */
+ MAGIC_F = 0xbadc0c0a, /* Free block */
+ MAGIC_E = 0xdeadbabe, /* End of arena */
+ MAGIC_I = 0xabba /* Block is immutable (hidden from gc) */
+};
+
+struct Bhdr
+{
+ u32 magic;
+ u32 size;
+ intptr allocpc;
+ intptr reallocpc;
+ union {
+ uchar data[1];
+ struct {
+ Bhdr* bhl;
+ Bhdr* bhr;
+ Bhdr* bhp;
+ Bhdr* bhv;
+ Bhdr* bhf;
+ } s;
+#define clink u.l.link
+#define csize u.l.size
+ struct {
+ Bhdr* link;
+ u32 size;
+ } l;
+ } u;
+};
+
+struct Btail
+{
+ /* ulong pad; */
+ Bhdr* hdr;
+};
+
+#define B2D(bp) ((void*)bp->u.data)
+#define D2B(b, dp) b = ((Bhdr*)(((uchar*)dp)-(((Bhdr*)0)->u.data))); \
+ if(b->magic != MAGIC_A && b->magic != MAGIC_I)\
+ poolfault(dp, "alloc:D2B", getcallerpc(&dp));
+#define B2NB(b) ((Bhdr*)((uchar*)b + b->size))
+#define B2PT(b) ((Btail*)((uchar*)b - sizeof(Btail)))
+#define B2T(b) ((Btail*)(((uchar*)b)+b->size-sizeof(Btail)))
+
+#define B2LIMIT(b) ((Bhdr*)((uchar*)b + b->csize))
+
+#define BHDRSIZE ((u32)(((Bhdr*)0)->u.data)+sizeof(Btail))
+
+extern void (*poolfault)(void *, char *, uintptr);
+extern void poolinit(void);
+extern void* poolalloc(Pool*, ulong);
+extern void poolfree(Pool*, void*);
+extern Bhdr* poolchain(Pool*);
+extern int poolcompact(Pool*);
+extern void poolimmutable(void*);
+extern ulong poolmsize(Pool*, void*);
+extern void poolmutable(void*);
+extern char* poolname(Pool*);
+extern int poolread(char*, int, uintptr);
+extern void* poolrealloc(Pool*, void*, ulong);
+extern int poolsetsize(char*, int);
+extern void poolsetcompact(Pool*, void (*)(void*, void*));
+extern char* poolaudit(char*(*)(int, Bhdr *));
+
+extern void (*poolmonitor)(int, ulong, Bhdr*, ulong);
+extern void showframe(void *f, void *t);